0

I was trying to use the below code to iterate on char array elements on my PC.

#include <stdio.h>

int main(int argc , char *argv[] , char* env[]){

    char szBuffer[] = {'A' , 'B' , '4' , 'y' , 't' , 'A' , 'B' , '4' , 'y' , 't' }; 

    int i;
    for ( i = 0; szBuffer[i]; i++)
           printf( "i = %d  -------- (int)szBuffer[i] = %d  --------\n", i , (int)szBuffer[i]);
    return 0;
}

But expected result did not achieve. My result:

i = 0  -------- (int)szBuffer[i] = 65  --------
i = 1  -------- (int)szBuffer[i] = 66  --------
i = 2  -------- (int)szBuffer[i] = 52  --------
i = 3  -------- (int)szBuffer[i] = 121  --------
i = 4  -------- (int)szBuffer[i] = 116  --------
i = 5  -------- (int)szBuffer[i] = 65  --------
i = 6  -------- (int)szBuffer[i] = 66  --------
i = 7  -------- (int)szBuffer[i] = 52  --------
i = 8  -------- (int)szBuffer[i] = 121  --------
i = 9  -------- (int)szBuffer[i] = 116  --------
i = 10  -------- (int)szBuffer[i] = 64  --------

But online C compiler shows the rational result as I expected. Online compiler:

i = 0  -------- (int)szBuffer[i] = 65  --------
i = 1  -------- (int)szBuffer[i] = 66  --------
i = 2  -------- (int)szBuffer[i] = 52  --------
i = 3  -------- (int)szBuffer[i] = 121  --------
i = 4  -------- (int)szBuffer[i] = 116  --------
i = 5  -------- (int)szBuffer[i] = 65  --------
i = 6  -------- (int)szBuffer[i] = 66  --------
i = 7  -------- (int)szBuffer[i] = 52  --------
i = 8  -------- (int)szBuffer[i] = 121  --------
i = 9  -------- (int)szBuffer[i] = 116  --------

So confusing for me! How does that 10th iteration show and why always have 64('@') value?

  • 2
    Why do you expect `szBuffer[i]` to ever evaluate to zero? You didn't add a null terminator so this is not a C string. Add `'\0'` at the end of your array. – Lundin May 09 '22 at 10:02
  • You need to null-terminate `szBuffer`. If you use a double-quoted string to initialize an array, e.g. `"abc"`, then a terminating `\0` character is added automatically. But if you use array initializer syntax to initialize the individual elements, e.g. `{'a', 'b', 'c'}`, then the initializer is not treated as a string and there is no terminating `\0` character. Look at `sizeof(szBuffer)` to see this for yourself. – Tom Karzes May 09 '22 at 10:06
  • @Lundin I know your tip but why this work then? or why this for loop stop at 10 or 11 steps! normally we need zero for terminating iteration but there is no zero when we don't have `\0`at the end of array! – Mohammad RafatPanah May 09 '22 at 10:19
  • @MohammadRafatPanah Just because you didn't explicitly place a null character there doesn't mean that the garbage following it *isn't* a null character. Do you think it guarantees that the first byte following an array is never a null character? It can be anything. That's why it's called undefined behavior. If you want a guaranteed null character at the end, then *put it there*. Add `'\0'` to the end of the initializer list. – Tom Karzes May 09 '22 at 10:26
  • @TomKarzes So it depends on what value did exist in memory and randomly can iterate random times? thank you! – Mohammad RafatPanah May 09 '22 at 10:31
  • @MohammadRafatPanah [What is undefined behavior and how does it work?](https://software.codidact.com/posts/277486) – Lundin May 09 '22 at 10:31

1 Answers1

1

I guess this Undefined Behavior(UB) was caused by the stack. You can use this code and run it on different machines and different compilers, even different options when you compile this code. You may get different results.

#include <stdio.h>

int main(){
    char buf[] = {'A'};
    for(int i = 0; buf[i]; i++){
        printf("i: %d, buf[i]: %c\n", i, buf[i]);
    }
}

bufis on the stack. If 0x00 is stored after buf, the for loop will only print once, but if it stores other valid numbers, it will continue to print. Of course, if, unfortunately, i keep increasing until it reaches an area where you don't have read permission, it will panic.

There are some ways to avoid this UB:

  1. End with \0: char buf[] = {'A', 0};
  2. Enhance for-loop: for(unsigned i = 0; i < sizeof(buf)/sizeof(char);i++){...}
h3n4l
  • 36
  • 4