Commandline and Lvalue

Discussion in 'C' started by shyam_oec, Jun 30, 2008.

  1. shyam_oec

    shyam_oec New Member

    Joined:
    Nov 26, 2007
    Messages:
    89
    Likes Received:
    1
    Trophy Points:
    0
    Occupation:
    Software Developer, .NET Framework
    Location:
    Jamshedpur
    void main(int argc,char *argv[])
    {
    printf("\n%c",++(*(++(*++argv))));
    }


    Running the executable file of this program at command line,with arguments 'PR5 aabbcc' gave output 's'.
    can u explain how it worked.
    I still have a doubt,that how it compiled well,since in statement '++argv',i think
    compiler should have given Lvalue error,but it is running well!plese explain how?
     
  2. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    It's undefined, because you're using multiple operations with side effects in the same calculation. So anything could happen, including monkeys flying out of your nose.

    When I ran it without parameters I got an access violation reading location 0x00000002. This should be a clue.
    When I ran it with parameters PR5 aabbcc I got the output 6.
    When I realised argv was _TCHAR *[] and changed it to char *[], I then got the output 'S' (although uppercase, not lowercase as in your example).
    The expression argv[1][1]+1 evaluates to 'S', doesn't use side effects and is not undefined.

    If you want to determine exactly what it's doing in your specific situation, for interest only rather than for use anywhere else, then run repeated tests building up the expression from the first operation and see what it displays each time. Don't forget to change the format string to match whatever it's doing. For example:
    printf("%s\n",*++argv); // %s because *++argv is a string
    printf("%s\n",++(*++argv)); // %s because a string pointer preincremented is still a string pointer
    printf("%c\n",*(++(*++argv))); // %c because dereferencing a string pointer gives a character
    ...and so on.

    Compiler implementors are free to determine when they apply side effects, which is why the behaviour is undefined. Taking a simpler example i++ + i++, this may be implemented as equivalent to
    i + (i+1); i+=2;, or
    i+i; i+=2;, or
    (i+1) + i; i+=2;
    and possibly other ways. In the first case the postincrement happens immediately after the value of i is taken, and this happens as the expression is parsed from left to right. In the second case the two postincrements aren't applied until after the calculation is over. The third is the same as the first except that the expression is parsed from right to left. In the second the result of the addition is 2, but in the other two the result is 3.

    So if you preincrement argv, dereference it and preincrement the result, then dereference and preincrement that, a number of different things could happen depending on what was on the compiler implentor's mind at the time. Try:

    int main(int argc,char *argv[])
    {
    char **argv_reset=argv;
    printf("(1) argv[0]=%s\natgv[1]=%s\nargv[2]=%s\n",argv[0],argv[1],argv[2]);
    printf("%c\n",++(*(++(*++argv))));
    printf("(2) argv[0]=%s\natgv[1]=%s\nargv[2]=%s\n",argv[0],argv[1],argv[2]);
    argv=argv_reset;
    printf("(3) argv[0]=%s\natgv[1]=%s\nargv[2]=%s\n",argv[0],argv[1],argv[2]);
    }
    and see what you get.
     
    shabbir likes this.
  3. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Very well explained xpi0t0s, Some Repu comes your way
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice