A loop starting at -1 doesn't print anything

This program should print array elements, but when it is running, the output is not output.

 #include <stdio.h> #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0])) int array[] = { 23, 34, 12, 17, 204, 99, 16 }; int main() { int d; for (d = -1; d <= (TOTAL_ELEMENTS - 2); d++) printf("%d\n", array[d + 1]); return 0; } 

Why does this program not show any output?

+50
c sizeof loops integer negative-number
Aug 13 '17 at 5:48 on
source share
3 answers

sizeof returns an unsigned integer, so TOTAL_ELEMENTS also unsigned.

d . Initially, d is -1 . However, when comparing, d implicitly displayed unsigned, so when comparing with TOTAL_ELEMENTS it is no longer -1 , it is actually UINT_MAX (which is 4294967295 on my machine, but may differ for others).

Besides,

If you want to fix this, enter TOTAL_ELEMENTS in int :

 for(d = -1; d <= (int)(TOTAL_ELEMENTS - 2); d++) 

This will print:

 23 34 12 17 204 99 16 

As expected. You can also see the comparison operation for unsigned integers and sign for more information on the topic of comparisons without signatures.

It's worth noting that turning on compiler warnings would help you figure out what's going on (as hyde noted in comment ):

 $ gcc -Wall -Wextra test.c test.c:7:17: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare] for(d = 0; d < TOTAL_ELEMENTS; d++) ~ ^ ~~~~~~~~~~~~~~ 1 warning generated. 



Alternatively, why not start d at 0 and instead switch to TOTAL_ELEMENTS - 1 ? You can even refuse to typecast, which is necessary only for the angular case d = -1 .

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



The relevant standard C99 passages are given as footnotes:

  • 6.3.1.8p2 defines a conversion from an unsigned signed type.

    If an operand that has an unsigned integer type has a rank greater than or equal to the ranks of the type of another operand, then the operand with a signed integer type is converted to the operand type with an unsigned integer.

  • 6.3.1.3p2 determines how the conversion is performed: by adding UINT_MAX + 1 to the signed view.

    If the new type is unsigned, the value is converted by repeatedly adding or subtracting more than one maximum value that can be represented in the new type until the value is in the range of the new type.

    So -1 => -1 + (UINT_MAX + 1) = UINT_MAX , for this scenario.

+141
Aug 13 '17 at 5:58 on
source share

My gcc displays this warning:

 warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare] for(d = 0; d < TOTAL_ELEMENTS; d++) 

which means that (TOTAL_ELEMENTS-2) is unsigned int , and d is signed int . This makes the expression always false for the initial value of d , since (unsigned int)(-1) > (TOTAL_ELEMENTS-2) .

+33
Aug 13 '17 at 5:58 on
source share

Binary operations between different types of integrals are performed in a "general" type defined by so-called ordinary arithmetic transformations. Thus, int d has a single type, initialized with a value of -1. Which, when converted to unsigned int, returns a maximum of unsigned int, which is much larger than the value returned by TOTAL_ELEMENTS.

+4
Aug 13 '17 at 9:35 on
source share



All Articles