By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,227 Members | 1,175 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,227 IT Pros & Developers. It's quick & easy.

int to unsigned int conversions

P: n/a
Hi,
This was asked on our school newsgroup by a friend of mine.
He gave the following code and said that it did not print out
the elements of the array. He asked for an explanation for this
behaviour. I whittled this down a bit but I am unable to pin it
to a reference from the standard which I would like to have given
when explaining it.
Ok here goes.

#include <stdio.h>
#include <stdlib.h>

#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};

int main(void)
{
int d;

for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
/* TOTAL_ELEMENTS is actually getting evaluated to an unsigned
int. Since sizeof returns size_t which is unsigned int.
I assume that this is the problem since the problem was reproduced
if I used this line instead:
for(d=-1;d <= ((unsigned int)7-2);d++)

This for some reason is either implementation defined behaviour
or undefined behaviour since I got two separate outputs from two
compilers.. one being Turbo C and one the VC compiler.
In one case it is not printing out any element of the array
since the LHS is forcing itself up into unsigned int ...
In the other case the unsigned int is coverted into an int, thus
there are no problems.
*/

printf("%d\n",array[d+1]);

return EXIT_SUCCESS;
}
Would like to hear your comments regarding the above explanation.
Regards,
Anupam
Nov 13 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Anupam wrote:

Hi,
This was asked on our school newsgroup by a friend of mine.
He gave the following code and said that it did not print out
the elements of the array. He asked for an explanation for this
behaviour. I whittled this down a bit but I am unable to pin it
to a reference from the standard which I would like to have given
when explaining it.
Ok here goes.

#include <stdio.h>
#include <stdlib.h>

#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};

int main(void)
{
int d;

for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
/* TOTAL_ELEMENTS is actually getting evaluated to an unsigned
int. Since sizeof returns size_t which is unsigned int.
I assume that this is the problem since the problem was reproduced
if I used this line instead:
for(d=-1;d <= ((unsigned int)7-2);d++)

This for some reason is either implementation defined behaviour
or undefined behaviour since I got two separate outputs from two
compilers.. one being Turbo C and one the VC compiler.
In one case it is not printing out any element of the array
since the LHS is forcing itself up into unsigned int ...
In the other case the unsigned int is coverted into an int, thus
there are no problems.
*/

printf("%d\n",array[d+1]);

return EXIT_SUCCESS;
}
Would like to hear your comments regarding the above explanation.


for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
should not print unless you have a situation where
size_t gets converted to int, because that's the only way
that -1 can be less than or equal to (size_t)5.
If size_t is unsigned short and unsigned short
has fewer value bits than int does, it should work.

If -1 is converted to an unsigned type,
then it is converted to the greatest value
that the unsigned type is capable of representing.

for(d=-1;d <= ((unsigned int)7-2);d++)
should not print at all.

for(d=-1;d <= (int)(TOTAL_ELEMENTS-2);d++)
should print the array.

--
pete
Nov 13 '05 #2

P: n/a
On 3 Dec 2003 03:33:42 -0800
an**************@persistent.co.in (Anupam) wrote:
Hi,
This was asked on our school newsgroup by a friend of mine.
He gave the following code and said that it did not print out
the elements of the array. He asked for an explanation for this
behaviour. I whittled this down a bit but I am unable to pin it
to a reference from the standard which I would like to have given
when explaining it.
Ok here goes.

#include <stdio.h>
#include <stdlib.h>

#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};

int main(void)
{
int d;

for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
/* TOTAL_ELEMENTS is actually getting evaluated to an unsigned
int. Since sizeof returns size_t which is unsigned int.
Is that true of both compilers you were trying? It is only required to
be an unsigned integer type so it could be unsigned long.

However, a more normal (and more reliable) way to do this loop is

for (d=0; d<TOTAL_ELEMENTS; d++)

to make certain that the above works for the maximum possible size of
array you would have to declare d as being of type size_t.
I assume that this is the problem since the problem was reproduced
if I used this line instead:
for(d=-1;d <= ((unsigned int)7-2);d++)

This for some reason is either implementation defined behaviour
or undefined behaviour since I got two separate outputs from two
Implementation defined.
compilers.. one being Turbo C and one the VC compiler.
In one case it is not printing out any element of the array
since the LHS is forcing itself up into unsigned int ...
In the other case the unsigned int is coverted into an int, thus
there are no problems.
*/

printf("%d\n",array[d+1]);

return EXIT_SUCCESS;
}
Would like to hear your comments regarding the above explanation.
Regards,


You are on the right lines, however the exact promotions applied depend
on how the implementation has chosen to define size_t, which on old DOS
and Windows compilers may depend on the options used.

If size_t is unsigned short and an int can represent all values of
unsigned short then it will be promoted to int. This may be the case if
you select the small memory model and an option that gives you 32 bit
ints.

Basically, your friend should not write his loops like that.

Look up "Arithmetic Conversions", "Integral Promotion" and "Integral
Conversion" for the full gory details
--
Mark Gordon
Paid to be a Geek & a Senior Software Developer
Although my email address says spamtrap, it is real and I read it.
Nov 13 '05 #3

P: n/a
In <aa*************************@posting.google.com> an**************@persistent.co.in (Anupam) writes:
#include <stdio.h>
#include <stdlib.h>

#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};

int main(void)
{
int d;

for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
/* TOTAL_ELEMENTS is actually getting evaluated to an unsigned
int. Since sizeof returns size_t which is unsigned int.
It's an unspecified usigned integer type.
I assume that this is the problem since the problem was reproduced
if I used this line instead:
for(d=-1;d <= ((unsigned int)7-2);d++)

This for some reason is either implementation defined behaviour
or undefined behaviour since I got two separate outputs from two
compilers.. one being Turbo C and one the VC compiler.
Except for the pathological case when size_t is unsigned char or unsigned
short, the behaviour is well defined: d is converted to size_t (an
unsigned integer type) before the comparison.
In one case it is not printing out any element of the array
since the LHS is forcing itself up into unsigned int ...
This is the correct behaviour. When converting -1 to an unsigned type,
the result is the maximum value representable by theat type.
In the other case the unsigned int is coverted into an int, thus
there are no problems.


That compiler is broken. Neither Turbo C nor VC have a size_t that is
subject to the integral promotions, therefore there is no way a size_t
expression will be converted to int by the usual arithmetic conversions.

The general rule is that if you mix signed and unsigned integers in the
same expression, the signed integers must be non-negative in order to get
what you intuitively expect. Fix your loop to the idiomatic

for (d = 0; d < TOTAL_ELEMENTS; d++)
printf("%d\n", array[d]);

and everything will work just fine.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #4

P: n/a
In article <aa*************************@posting.google.com> ,
an**************@persistent.co.in (Anupam) wrote:
#include <stdio.h>
#include <stdlib.h>

#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};

int main(void)
{
int d;

for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
/* TOTAL_ELEMENTS is actually getting evaluated to an unsigned
int. Since sizeof returns size_t which is unsigned int.
I assume that this is the problem since the problem was reproduced
if I used this line instead:
for(d=-1;d <= ((unsigned int)7-2);d++)

This for some reason is either implementation defined behaviour
or undefined behaviour since I got two separate outputs from two
compilers.. one being Turbo C and one the VC compiler.
In one case it is not printing out any element of the array
since the LHS is forcing itself up into unsigned int ...
In the other case the unsigned int is coverted into an int, thus
there are no problems.
*/

printf("%d\n",array[d+1]);

return EXIT_SUCCESS;
}
Would like to hear your comments regarding the above explanation.
Regards,
Anupam


It gives you the right idea, just very slightly inaccurate. size_t can
be any unsigned type, not just unsigned int. But the important thing is
that depending on the implementation, d may be converted to an unsigned
type and therefore the loop will not print anything. Shows that you have
to be very careful mixing signed and unsigned operands.
Nov 13 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.