Thread: Point arithmetic

  1. #1
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694

    Point arithmetic

    As my name says, I am a student, thus my exam's in C comes this Thursday!
    So, I took a simulation of the final exams, with the exams of the previous year. I did well, but I missed question k on pointer arithmetic subject. I thought that the behavior was undefined, but A is printed normally. :/ Why?
    In my mind, pointer s is at the start of the string literal, we move it one position backwards and then we pass it in strlen! So what we pass in strlen is memory that is not ours!

    Code
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
            char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("*(s+2) = %c\n", *(s+2));
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
    /*ERROR  printf("**s = %c\n", **s);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";*/
    
            printf("c)UNDEFINED *(s+*s) = %c\n", *(s+*s));
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("d) s[6] = %c\n", s[6]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("e) (&(s[2]))[-1] = %c\n", (&(s[2]))[-1]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("f) (&(s[-1]))[2] = %c\n", (&(s[-1]))[2]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("g) *(s++) = %c\n", *(s++));
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("h) *(++s) = %c\n", *(++s));
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("i) s[strlen(s)-1] = %c\n", s[strlen(s)-1]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("j) s[strlen(s + 1)] = %c\n", s[strlen(s + 1)]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("k)UNDEFINED s[strlen(s - 1)] = %c\n", s[strlen(s - 1)]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     printf("l) s[strlen(s + 1)-1] = %c\n", s[strlen(s + 1)-1]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("m) *(s--) = %c\n", *(s--));
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("n)UNDEFINED  *(--s) = %c\n", *(--s));
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("o) s[*(s+6)-s[4]] = %c\n", s[*(s+6)-s[4]]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("p)UNDEFINED s[*(s+6)-4] = %c\n", s[*(s+6)-4]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("q) s[*(s+4)-*(s+3)] = %c\n", s[*(s+4)-*(s+3)]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("r)NULL TERMINATOR *(s+strlen(s)) = %c\n", *(s+strlen(s)));
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            printf("s) s[*(s+strlen(s))] = %c\n", s[*(s+strlen(s))]);
            s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
            return 0;
    }
    Output
    Code:
    *(s+2) = C
    c)UNDEFINED *(s+*s) =
    d) s[6] = G
    e) (&(s[2]))[-1] = B
    f) (&(s[-1]))[2] = B
    g) *(s++) = A
    h) *(++s) = B
    i) s[strlen(s)-1] = Z
    j) s[strlen(s + 1)] = Z
    k)UNDEFINED s[strlen(s - 1)] = A
    l) s[strlen(s + 1)-1] = Y
    m) *(s--) = A
    n)UNDEFINED  *(--s) =
    o) s[*(s+6)-s[4]] = C
    p)UNDEFINED s[*(s+6)-4] = )
    q) s[*(s+4)-*(s+3)] = B
    r)NULL TERMINATOR *(s+strlen(s)) =
    s) s[*(s+strlen(s))] = A
    linux05:/home/users/std10093>
    /* I decided to upload the whole question, because all the students have or are about to have exams, so they can practice a bit. Moreover, for the no-students members, I know that this will make them remember something they probably have forgotten. */
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  2. #2
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by std10093 View Post
    I did well, but I missed question k on pointer arithmetic subject. I thought that the behavior was undefined, but A is printed normally. :/ Why?
    When behaviour is undefined, it only means that you can't say anything about what happens. For example, perhaps it is undefined and A *is* printed normally. Why not? That being said, if s points to the beginning of a string literal, then I don't see how s[strlen(s-1)] could be defined.

    Simply stating that you were able to print it with no problem does not mean it is a valid expression.

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by std10093 View Post
    So, I took a simulation of the final exams, with the exams of the previous year. I did well, but I missed question k on pointer arithmetic subject. I thought that the behavior was undefined, but A is printed normally. :/ Why?
    Part of undefined behaviour is that it sometimes looks like it works. In your case it happens that the byte in front of s has the value 0. Thus strlen() returns 0 and you get a valid index for s.

    Look at this example:
    Code:
    #include <stdio.h>
    #include <string.h>
     
    int main(void)
    {
        char *a = "999";
        char* s = "ABCD";
        char *b = "111";
     
        printf("a: %p - b: %p - s: %p\n", (void *)a, (void*)b, (void*)s);
        printf("%c(%d) - %u\n", *(s - 1), *(s - 1), strlen(s - 1));
        printf("k)UNDEFINED s[strlen(s - 1)] = %c\n", s[strlen(s - 1)]);
        
        char a2[] = {'Y', 'Y', 'Y', 'Y', 'Y' };
        char s2[] = "ABCD"; 
        char b2[] = {'X', 'X', 'X', 'X', 'X' };
    
        printf("a2: %p - b2: %p - s2: %p\n", (void *)a2, (void*)b2, (void*)s2);
        printf("%c(%d) - %u\n", *(s2 - 1), *(s2 - 1), strlen(s2 - 1));
        printf("k)UNDEFINED s2[strlen(s2 - 1)] = %c\n", s2[strlen(s2 - 1)]);
    
        return 0;
    }
    which produces this output on my computer:
    Code:
    $ ./foo
    a: 0x8048700 - b: 0x8048709 - s: 0x8048704
    (0) - 0
    k)UNDEFINED s[strlen(s - 1)] = A
    a2: 0xbf8474ad - b2: 0xbf8474b7 - s2: 0xbf8474b2
    Y(89) - 5
    k)UNDEFINED s2[strlen(s2 - 1)] = X
    In the first block, all three string literals are stored next to each other. Thus the byte just in front of "s" is the null character of the string "a".

    In the second block I use char arrays in order to influence the byte in front of "s2". As you can see in the output, it's the last character of array "a2". strlen() starts at this character and continues until it reaches the null character of "s2". Hence the length is one character too much. You can also see by looking at the addresses, that "b2" is again behind "s2" and now you are accessing the first character of "b2" (a 'X').

    Bye, Andreas

  4. #4
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Thanks both for the good replies. So, my answer "UNDEFINED" is correct I guess
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 04-27-2011, 04:34 AM
  2. Floating Point Bit Level Arithmetic
    By DanV2 in forum C Programming
    Replies: 15
    Last Post: 10-26-2010, 01:50 PM
  3. Basic floating point arithmetic not working...
    By zodiacWarrior in forum C++ Programming
    Replies: 2
    Last Post: 08-11-2008, 10:16 AM
  4. Point to Point Protocol and Bluetooth DUN
    By PSLoh in forum Networking/Device Communication
    Replies: 2
    Last Post: 03-03-2008, 09:44 AM
  5. Floating point faster than fixed-point
    By VirtualAce in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 11-08-2001, 11:34 PM