Are FOR loops with char iterators in C possible?

2019-07-15 01:55发布

问题:

I'm having a problem using an unsigned char as an iterator. Using the following code results in being stuck inside a FOR loop. The output looks like this.

unsigned char i;
char * arr;
int * freq;
arr = (char *)(malloc(256*sizeof(char)));
freq = (int *)(malloc(256*sizeof(int)));
for (i=0; i<=255;i++){
    arr[i]=i;
    freq[i]=0;
    printf("%c",i);
}

My question is why this happens? Is it due to using an unsigned char as an iterator?

回答1:

i <= 255

If i is of type unsigned char and that type is 8 bit on your platform (which it likely is), then the expression will always be true and you have an infinite loop. It is well-defined behavior, though. The unsigned char will simply wrap around and its value will start at 0 again once it has reached 255.

The solution is simple of course: change the type of i to int.

To avoid such surprises in the future, make sure to turn on your compiler's warnings. If I compile the bogus loop with GCC and pass it the -Wall and -Wextra flags, it will tell me this.

main.c: In function ‘main’:
main.c:5:17: warning: comparison is always true due to limited range of data type [-Wtype-limits]
   for (i = 0; i <= 255; ++i)
                 ^


回答2:

Primary issue: Since unsigned char i cannot hold a value greater than UCHAR_MAX. i<=255 is always true. UCHAR_MAX is commonly 255, as it certainly is on OP's platform, but may be more.

Other notes:

When using an array index, best to use size_t.

Casting malloc() results is not needed. Also consider multiple by the size of the variable and not the size of the type. - IMO: easier to maintain and code correctly.

Avoid magic numbers 256, 255 floating about.

#define N 256
size_t i;
char * arr;
int * freq;
arr = malloc(sizeof *arr * N);
freq = malloc(sizeof *freq * N);
for (i=0; i<N;i++){
    arr[i]=i;
    freq[i]=0;
    printf("%c",i);
}


回答3:

A for loop does the following: It performs the initialisation. Then it checks the loop condition. If the loop condition is true, it performs the loop, then the increment expression. And then it checks the loop condition again. This is literally what it does.

When i = 255, and i++ is executed, the compiler tries to set i to 256, but because it is an unsigned char and likely 8 bit, that 256 is truncated to zero. And then the loop condition i <= 255 is again true. The compiler follows exactly what you told it to do, not what you wanted it to do.



回答4:

Because your condition is i <= 255, when i becomes 255, it will be incremented by one. The maximum range of an unsigned char at your machine is [0,255], so it just wrap around to zero again. So the loop, continues for ever.

This issue is known as arithmetic or integer overflow