1. No Profile Picture
Junior Member
Devshed Newbie (0 - 499 posts)

Join Date
Jun 2003
Location
Gloucester, Glos
Posts
9
Rep Power
0

#### pointer?

Hello

Can anyone expalin what is going on here.

char* q;

*(q=Q(B,"TH"))=0; //This is the line I am not sure about!

q is being assigned to the char* return from Q(), why is it being
set as a pointer by *(, and set to zero?, Q() returns either char* or zero.

p=B+2;
S()&&(p=q+4,l=S()-1); //q is being accessed again here.

Thanks
Dave
2. Code:
` *(q=Q(B,"TH"))=0;`
Ok, let's just pick that line apart:

Code:
`Q(B, "TH")`
You haven't shown how Q is defined, only that it returns a char*. That char* value is assigned to q:

Code:
`q = Q(B, "TH")`
The author of the obscure line of code then tries to set the assigned character string to the empty string (you know, to "", meaning that the first character is the NUL byte, or 0). He's trying to do it in one line though, when he could've done it in two (that would've been a good idea; now you are confused by it :)):

Code:
```q = Q(B, "TH")
*q = 0;```
To do this in one line, you have to realise that an assignment statement is actually also an expression, its value being the assigned value.

So what happens is, you evaluate an expression (Q(B, "TH")), assign it to q, then dereference the pointer, and assign the resulting character the value 0.

You can't write something like

Code:
`*q = Q(B, "TH") = 0`
that just doesn't make sense. You have to seperate the assignment and dereference operations using a set of parentheses:

Code:
` *(q = Q(B, "TH")) = 0`
3. Code:
`S()&&(p=q+4,l=S()-1);`
That's a nice one, too. It uses the comma operator to cram two statements into a spot where only one is expected. Also, the && construct is cute. In this particular case it acts sort of like an IF statement.

The thing is, logical operators are short-circuited in C, meaning:

In an AND expression, expr1 && expr2, expr2 is evaluated if, and only if expr1 evaluates to True.

Likewise, in an OR expression, expr1 || expr2, expr2 is evaluated if, and only if expr1 is False.

This means that the "expr2" in this case, (p=q+4,l=S()-1), is only evaluated is S() returns True.

Ok, now for the p=q+4,l=S()-1 bit.

These are basically two expressions, p=q+4 and l = S() - 1.

Now, these expressions are actually statements, which makes sense since the value of the AND operator is discarded anyway. The whole thing is just a nasty way of writing out the equivalent IF statement:

Code:
```if (S()) {
p = q+4;
l = S() - 1;
}```
It's all perfectly good C, but personally I think it's a bad habit to use C constructs this way. It's not going to make the code run any faster (not with today's optimising compilers, anyway), yet makes the code a LOT more difficult to read. The writer is either being lazy (the AND statement is shorter, obviously, so it's less typing), or he's trying to be smart. :rolleyes:

I really think trying to write easy-to-read code is a virtue that every professional programmer should have, or at least aspire to ;)
4. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Jul 2003
Location
Whyalla, Australia
Posts
20
Rep Power
0
OMG Analyser, I understood what you said when you explained it, but I never would have known any of that if you hadn't. When I first saw it I thought both of the lines would compile as errors (and I've been doing C++ for a year and a half now).

Where do you learn stuff like that? Were you taught it or just picked it up with experience? Or did you just spend hours looking at the code and took an educated guess? ;)
5. No Profile Picture
Junior Member
Devshed Newbie (0 - 499 posts)

Join Date
Jun 2003
Location
Gloucester, Glos
Posts
9
Rep Power
0
Thanks for the replies the code is from expert c programming by Peter Van Der Linden, I am interested as it is part of a Basic interpreter which was entered in the obfuscated c code competition hence it is very obscure the piece of code decodes IF F =0 THEN 3070 statements this line being in this state when it enters the Q() function: IFF=0THEN3070.
I am wondering why the first byte is being set to zero or the NULL terminator as pointer q is being accessed further down here
S()&&(p=q+4,l=S()-1) where pointer p is set to point @ "3070"
here is a line of the code I have been working on:

else //If statements
{

/* Q() returns a null pointer if the character(s) are
not found in the string B, if they are found it returns char*

This statement *(q=Q(B,"TH"))=0 appears to be setting

the pointer *q to zero or NULL, it is however accessed

below @ this line: S()&&(p=q+4,l=S()-1);
*/

*(q=Q(B,"TH"))=0; //Set the pointer *q up to
p= B+2; //Set p to *p= '=' of B, and call S()

/*if S() returns TRUE then p=q+4 which puts p @ the line
then set as l=S()-1
*/
S()&&(p=q+4,l=S()-1);
}

I wrote all this out before sending this post so I was on the right track but I am still unsure as why the first character of q is being set to the NULL terminator?, I always think of this as the end of string character.
Thanks
Dave.
6. Thanks for the kind words, stovellp :)

I learned C by reading a lot of books, including the book djwilliams37 seems to be reading now, Peter van der Linden's Expert C Programming. Combined with plenty of exercise, of course. You learn best by just trying :)

First off, be precise. A string terminator is called a NUL-byte or NUL-terminator. You should not confuse this with the NULL-pointer. They're two completely different things:

Code:
`*(q=Q(B,"TH"))=0`
does not set q to NULL. It sets the character that q points to to NUL. There's a difference.

And it makes sense, too. The snippet you're showing is most likely part of a tokenizer; it reads the IF keyword, the expression (F=0), the THEN keyword, followed by the line-number expression.

After that, all the interpreter really knows is that there's a valid IF statement, but it still needs to evaluate the if clause (the F=0 bit), and the line number.

Assume that the entire IF statement is held in a string, pointed to by a variable called "s":

Code:
`s = "IFF=0THEN3070";`
At the time of the statement, B seems to point to the start of the THEN keyword, or rather:

Code:
`B = s+5;`
Now, my guess is that there's a char* variable somewhere in that code you're looking at that points to the start of the IF clause (F=0):

Code:
`C = s+2;`
Then it all of a sudden, this makes sense:

Code:
`*(q=Q(B,"TH"))=0`
It tests for the first two characters of the THEN keyword, and if they're there, the T is changed to a NUL-byte, effectively NUL-terminating the string that C points to, the expression.

That's convenient! Now that it's NUL-terminated, you can just send it through the expression evaluation code, and you're done! :)

There is a danger here, though. q is dereferenced, regardless of what Q(B, "TH") returns. That means it will try to dereference a NULL pointer if there's an invalid IF statement (like with a possible typo, IFF=0HTEN3070).

I really can't say much about the rest of the code; I'd have to see more of it to make sense of it.
7. No Profile Picture
Junior Member
Devshed Newbie (0 - 499 posts)

Join Date
Jun 2003
Location
Gloucester, Glos
Posts
9
Rep Power
0
I think I have cracked it if anyone is interested:

else //If statements
{

/* Q() returns a null pointer if the character(s) are
not found in the string B, if they are found it returns char*

This statement *(q=Q(B,"TH"))=0 appears to be setting
the pointer *q to zero or NULL, it is however accessed below @ this line: S()&&(p=q+4,l=S()-1);
*/

//*(q=Q(B,"TH"))=0; //

q=Q(B,"TH");//Get the returned value from Q()
*q=0; //NULL out the character that q points to in B

/* In the case of IFF=0THEN3070, Q() returns "THEN3070"
After setting the character that q points to to NULL
B= "IFF=0""HEN3070", q="" but still points to this address of B.
*/

/*NOTE this is why the null is inserted in the Byte of B
as @ this point p=B+2, p points to "F=0", the string has
been terminated at this point
*/
p= B+2;

/*if S() returns TRUE then p=q+4 which puts p @ the line
then set as l=S()-1
*/
if(S())
{

/*q still points to the NULL in B incrementing by 4 puts it @
the point "3070"
*/
p=q+4;

/*This point assigns the line number to l remembering
array indexing @ zero
*/
l=S()-1;
}//End If
}