This month’s Exercise is about finding the limits, or how large a signed or unsigned char value can get before it flips over to negative or to zero. And the trick is performing this feat in your code without using the defined constants for a char data type available in the limits.h header file.
I have a reason for choosing the char data type as opposed to something larger, which I’ll explain at the end of this post.
For my solution, I use int variable count to do the incrementing. Two while loops process signed char c and then unsigned char uc values, typecasting them from variable count. Tests are made in each loop to determine when the signed value is less than zero or when the unsigned value returns to zero.
2026_09-Exercise.c
#include <stdio.h>
int main()
{
int count;
char c;
unsigned char uc;
/* initialize counting variable */
count = 1;
/* signed test */
while(count)
{
c = (signed char)count;
if( c<0 )
{
printf("'signed char' overflow at %d\n",count-1);
break;
}
count++;
}
/* unsigned test */
while(count)
{
uc = (unsigned char)count;
if( uc==0 )
{
printf("'unsigned char' overflow at %d\n",count-1);
break;
}
count++;
}
return 0;
}
The value of count need not be reset between the loops as 128 is a valid unsigned char value whereas in the signed domain it’s read as -128. Here is the output from a sample run:
'signed char' overflow at 127 'unsigned char' overflow at 255
Similar tests can be preformed with other integer types. In fact, the original assignment I coded tests for overflow with all the integer data types. The problem is that it took a few hours for the long test to trigger. After six days, I stopped testing for long long overflows.
I don’t know whether my long long tests were flawless or that it really takes that long to overflow. Regardless, my recommendation is that you use the defined constants in the limits.h header file for overflow tests as opposed to coding your own tests, though it is an interesting exercise.
I hope that your solution met with success.
Every additional bit doubles the maximum value so you could double the amount you add each time. That would wizz through almost instantly.
I threw this together very quickly and it’s pretty rough but I think you can see what I’m getting at. I didn’t bother with longer types or signed but the same principle applies.
#include<stdio.h>
#include<math.h>
int main()
{
unsigned char uc;
int exponent = 1;
int power;
for(;;)
{
power = pow(2,exponent);
printf(“trying %d “, power);
uc = (unsigned char) power;
if(uc==0)
{
puts(“KERPOW”);
break;
}
else
{
puts(“OK”);
}
exponent++;
}
return 0;
}
This is the output.
trying 2 OK
trying 4 OK
trying 8 OK
trying 16 OK
trying 32 OK
trying 64 OK
trying 128 OK
trying 256 KERPOW
Nice!
Another bit of code cobbled together quickly. Disclaimer: might be trash! In its defence it does spit out the correct maximum for unsigned long long and it takes a fraction of a second. The second addition in the loop is 1 over the threshold where we could run out of bits and roll round to zero.
Note: locale.h, setlocale and the apostrophe in %’llu might not work for everyone.
#include
#include
#include
int main()
{
// max 18,446,744,073,709,551,615
setlocale(LC_NUMERIC, “”);
unsigned long long ulli = 1ULL;
unsigned long long addend = 1ULL;
while(ulli != 0ULL)
{
ulli += addend – 1;
printf(“%’llu\n”, ulli);
ulli += 1;
printf(“%’llu\n\n”, ulli);
if(ulli == 0)
puts(“The previous number is the maximum for unsigned long long”);
addend *= 2;
}
return 0;
}
This is the last few lines of the output:
18,446,744,073,709,551,615
0
The previous number is the maximum for unsigned long long
Sorry, I messed up the code.
#include<stdio.h>
#include<math.h>
#include <locale.h>
int main()
{
// max 18,446,744,073,709,551,615
setlocale(LC_NUMERIC, “”);
unsigned long long ulli = 1ULL;
unsigned long long addend = 1ULL;
while(ulli != 0ULL)
{
ulli += addend – 1;
printf(“%’llu\n”, ulli);
ulli += 1;
printf(“%’llu\n\n”, ulli);
if(ulli == 0)
puts(“The previous number is the maximum for unsigned long long”);
addend *= 2;
}
return 0;
}
Yeah, you need an up-to-date compiler to swallow that. It wouldn’t compile on clang 14, but works well on clang 20.