ULONG_MAX

C

ccwork

Hi all,
Is the following codes Standard C?

unsigned long number = ULONG_MAX;
unsigned long result = 0;

result = (unsigned long) number % ULONG_MAX;
printf("ULONG_MAX=%lu, number=%lu, result=%lu\n", ULONG_MAX, number,
result);

My compiler (VC++ if you want to know), in debug mode, give:
ULONG_MAX=4294967295, number3=4294967295, result3=0

However, in release mode, it gives:
ULONG_MAX=4294967295, number3=4294967295, result3=4294967295

I don't know if the code trigger undefined behaviour or it is the
compiler bug.
 
K

Keith Thompson

ccwork said:
Is the following codes Standard C?

unsigned long number = ULONG_MAX;
unsigned long result = 0;

result = (unsigned long) number % ULONG_MAX;
printf("ULONG_MAX=%lu, number=%lu, result=%lu\n", ULONG_MAX, number,
result);

My compiler (VC++ if you want to know), in debug mode, give:
ULONG_MAX=4294967295, number3=4294967295, result3=0

However, in release mode, it gives:
ULONG_MAX=4294967295, number3=4294967295, result3=4294967295

I don't know if the code trigger undefined behaviour or it is the
compiler bug.

It looks like it could be a compiler bug, but it's hard to be sure
since what you posted either isn't exactly your actual code, or isn't
your actual output. The printf statement has "number=" and "result=",
but the output you showed us has "number3=" and "result3=". It's
impossible to tell what other subtle differences there might be that
could explain the discrepancy.

Also, the cast is superfluous; number is already of type unsigned
long, so casting it is unnecessary (unless it's necessary to trigger
the compiler bug).

Here's a complete self-contained program (I've left the cast in place):

#include <stdio.h>
#include <limits.h>
int main(void)
{
unsigned long number = ULONG_MAX;
unsigned long result = 0;

result = (unsigned long) number % ULONG_MAX;
printf("ULONG_MAX=%lu, number=%lu, result=%lu\n",
ULONG_MAX, number, result);
return 0;
}

Save it to a file, compile it, and run it. If the output looks ok,
there may be some odd problem in your original code. If the problem
persists, post the exact output that you get. Be sure to
cut-and-paste it; don't attempt to re-type it.
 
C

ccwork

Keith said:
It looks like it could be a compiler bug, but it's hard to be sure
since what you posted either isn't exactly your actual code, or isn't
your actual output. The printf statement has "number=" and "result=",
but the output you showed us has "number3=" and "result3=". It's
impossible to tell what other subtle differences there might be that
could explain the discrepancy.

It is typo.
Also, the cast is superfluous; number is already of type unsigned
long, so casting it is unnecessary (unless it's necessary to trigger
the compiler bug).

Here's a complete self-contained program (I've left the cast in place):

#include <stdio.h>
#include <limits.h>
int main(void)
{
unsigned long number = ULONG_MAX;
unsigned long result = 0;

result = (unsigned long) number % ULONG_MAX;
printf("ULONG_MAX=%lu, number=%lu, result=%lu\n",
ULONG_MAX, number, result);
return 0;
}

Save it to a file, compile it, and run it. If the output looks ok,
there may be some odd problem in your original code. If the problem
persists, post the exact output that you get. Be sure to
cut-and-paste it; don't attempt to re-type it.

I try. In debug mode the result is:
ULONG_MAX=4294967295, number=4294967295, result=0

in release mode:
ULONG_MAX=4294967295, number=4294967295, result=4294967295
 
K

Keith Thompson

ccwork said:
Keith Thompson wrote: [snip]
Here's a complete self-contained program (I've left the cast in place):

#include <stdio.h>
#include <limits.h>
int main(void)
{
unsigned long number = ULONG_MAX;
unsigned long result = 0;

result = (unsigned long) number % ULONG_MAX;
printf("ULONG_MAX=%lu, number=%lu, result=%lu\n",
ULONG_MAX, number, result);
return 0;
}

Save it to a file, compile it, and run it. If the output looks ok,
there may be some odd problem in your original code. If the prnoblem
persists, post the exact output that you get. Be sure to
cut-and-paste it; don't attempt to re-type it.

I try. In debug mode the result is:
ULONG_MAX=4294967295, number=4294967295, result=0

in release mode:
ULONG_MAX=4294967295, number=4294967295, result=4294967295

Interesting. It does look like a compiler error. (The debug mode
output looks correct.)

I suggest posting to a system-specific newsgroup, probably
comp.os.ms-windows.programmer or one of the microsoft.* groups.
Specify exactly what version of the compiler (VC++, you said) you're
using. Maybe somebody else with the same version can try it; it could
be either a compiler bug or something specific to your system.
Examining the generated assembly code could also be useful (though of
course it's off-topic here).

You might also try it without the cast, and with unsigned int and
UINT_MAX rather than unsigned long and ULONG_MAX.

If it turns out to be a compiler bug, getting support from Microsoft
is left as an exercise.
 
C

Chris Croughton

I try. In debug mode the result is:
ULONG_MAX=4294967295, number=4294967295, result=0

in release mode:
ULONG_MAX=4294967295, number=4294967295, result=4294967295

It's a compiler optimisation bug of some sort. I just tried it with
VC6:

Default (no) optimisation:
> cl 1.c
> 1.exe
ULONG_MAX=4294967295, number=4294967295, result=0

Maximum optimisation:
> cl /Ox 1.c
> 1.exe
ULONG_MAX=4294967295, number=4294967295, result=4294967295

The actual one which does it is /Og ("enable global optimisation"), the
other optimisation switches seem to be OK (on my machine).

Report it to MS, and/or ask in a MS newsgroup. If you want help with
it, email me privately (it's not on-topic for comp.lang.c, but I'm
reporting here so others know to stop looking, I've crossposted and set
followups to comp.os.ms-windows.programmer.misc where it's probably more
on-topic).

Chris C
 
A

Andrey Tarasevich

ccwork said:
...
I try. In debug mode the result is:
ULONG_MAX=4294967295, number=4294967295, result=0

in release mode:
ULONG_MAX=4294967295, number=4294967295, result=4294967295
...

Definitely a compiler bug. If you try this

unsigned long foo(unsigned long number)
{
return number % ULONG_MAX;
}

compile this in Release configuration (i.e. optimizations enabled) the
resultant code for this function will look as follows

004010C0 mov eax,dword ptr [esp+4]

In C this is equivalent to a simple

unsigned long foo(unsigned long number)
{
return number;
}

i.e. the compiler does not even try to calculate the remainder, but
assumes instead that any 'unsigned long' value remains unchanged by the
above expression, which is not true.

A quick experiment shows that the compiler makes the same erroneous
assumption about 'unsigned int' values in 'number % UINT_MAX' expression.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top