Thread: pointer?

    #1
  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. #2
  3. *bounce*
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2002
    Location
    Delft, The Netherlands
    Posts
    514
    Rep Power
    42
    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
    "A poor programmer is he who blames his tools."
    http://analyser.oli.tudelft.nl/
  4. #3
  5. *bounce*
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2002
    Location
    Delft, The Netherlands
    Posts
    514
    Rep Power
    42
    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 ;)
    "A poor programmer is he who blames his tools."
    http://analyser.oli.tudelft.nl/
  6. #4
  7. 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? ;)
  8. #5
  9. 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
    number to jump to eg "3070", the line number counter is
    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.
  10. #6
  11. *bounce*
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2002
    Location
    Delft, The Netherlands
    Posts
    514
    Rep Power
    42
    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 :)

    Now, about djwilliams37's latest reply...

    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.
    "A poor programmer is he who blames his tools."
    http://analyser.oli.tudelft.nl/
  12. #7
  13. 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
    number to jump to eg "3070", the line number counter is
    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
    }

IMN logo majestic logo threadwatch logo seochat tools logo