Ron Ford said:
Can you spot the mistake in this printf call?
I think I got it:
Better.
//mkchars.c:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void)
{
FILE *fp;
char name[]="chars.256";
unsigned char c;
if ((fp = fopen(name, "wb")) == NULL)
{
printf("can't open %s\n", name);
I'd change this to:
fprintf(stderr, "can't open %s\n", name);
return EXIT_FAILURE;
}
else
{
for (c = 0; c <= UCHAR_MAX; c ++) {
As others have pointed out, this loop never terminates. c is of type
unsigned char; it's *always" <= UCHAR_MAX, no matter what you do with
it.
putc(c, fp);
}
fclose(fp);
}
return 0;
}
// gcc -o chars -std=c99 -pedantic -Wall -W mkchars4.c
I created a problem for myself that I don't get. I checked that UCHAR_MAX
was indeed 255 on my machine, but the subtitution for 255 causes this
warning and the program to hang:
C:\MinGW\source>gcc -o chars -std=c99 -pedantic -Wall -W mkchars3.c
mkchars3.c: In function 'main':
mkchars3.c:26: warning: comparison is always true due to limited range of
data type
I think I get it. 255 ++ = 0 ?
Um, no. 255++ is an error (specifically a constraint violation).
Remember, the "++" operator (prefix or postfix) does two things: it
modifies its argument, and it yields a value (either the previous
value or the modified value depending on where you put the "++").
You can't modify 255, so 255++ doesn't make any sense.
New C programmers are often fascinated by C's ++ operator. It's such
a cool and terse way to specify that you want to increment something.
But "x++" doesn't mean "x+1"; it's more complex than that. If you
want the incremented value of x without modifying x as a side effect,
just write "x+1". (And if you replace x with a constant 255,
you *can't* modify it.)
So what you're really asking is whether 255 + 1 == 0.
As stated, no, but there's a true statement hiding in there.
*If* UCHAR_MAX is 255 (as it very commonly is), and if you have an
object of type unsigned char with the value 255, then incrementing
that object will cause it to have the value 0.
For all unsigned types, arithmetic is performed in a wraparound
manner. So UINT_MAX + 1U == 0U, and ULONG_MAX + 1UL == 0UL.
Conversely, 0U - 1U == UINT_MAX.
And in many cases you still have to worry about promoitions and other
implicit conversions. For example, consider this:
#include <stdio.h>
#include <limits.h>
int main(void)
{
unsigned char c = UCHAR_MAX;
unsigned char c1 = c + 1;
int i1 = c + 1;
printf("c1 = %d\n", (int)c1);
printf("i1 = %d\n", i1);
return 0;
}
c1 gets the value 0; i1 gets the value 256. That's because, in the
expression c + 1, the value of c is implicitly promoted to int; adding
1 to an int value of 255 doesn't overflow or wrap around, it just
yields 256.
And although the initialization of c1 to c + 1 *acts* like it's adding
1 to an unsigned char value of 255, wrapping around, and yielding 0,
what really happens is that the value of c is promoted to int, the
expression c + 1 yields the int value 256, and that value is then
*converted* to unsigned char, yielding 0. The final result is the
same, but we took a detour from unsigned char to int and back to
unsigned char.
For integers, these implicit promotions only occur (and only in some
circumstances) for types narrower than int and unsigned int.