Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > int to unsigned int conversions

Reply
Thread Tools

int to unsigned int conversions

 
 
Anupam
Guest
Posts: n/a
 
      12-03-2003
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
 
Reply With Quote
 
 
 
 
pete
Guest
Posts: n/a
 
      12-03-2003
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
 
Reply With Quote
 
 
 
 
Mark Gordon
Guest
Posts: n/a
 
      12-03-2003
On 3 Dec 2003 03:33:42 -0800
http://www.velocityreviews.com/forums/(E-Mail Removed) (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.
 
Reply With Quote
 
Dan Pop
Guest
Posts: n/a
 
      12-03-2003
In <(E-Mail Removed)> (E-Mail Removed) (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: (E-Mail Removed)
 
Reply With Quote
 
Christian Bau
Guest
Posts: n/a
 
      12-03-2003
In article <(E-Mail Removed)> ,
(E-Mail Removed) (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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
(int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned):I'll loose something? pozz C Programming 12 03-20-2011 11:32 PM
int*unsigned int = unsigned? ciccio C++ 2 06-04-2010 01:54 PM
is vec.reserve(unsigned int) better than vec(unsigned int)? er C++ 6 09-14-2007 06:20 AM
Pointer conversions and Data types conversions vb@gmail.com C Programming 10 08-05-2005 09:51 AM
unsigned int const does not match const unsigned int Timo Freiberger C++ 3 10-30-2004 07:02 PM



Advertisments