-3

why there is no output for this?

#include <stdio.h>

int main() {
    int i;
    int array[4] = {10, 25, 36, 42};
    // int size=sizeof(array) / sizeof(int);
    for (i = -1; i < sizeof(array) / sizeof(int); i++) {
        printf("%d ", array[i+1]);
    }

    return 0;
}

Expected output is 10 25 36 42

10
  • 1
    It gets successfully compiled. But the expected output is not shown. Commented Oct 11, 2023 at 19:11
  • Why are you iterating from -1? I think, it's a negative value being casted to size_t. Commented Oct 11, 2023 at 19:11
  • @bereal Wow. gcc does not warn even with pedantic. Commented Oct 11, 2023 at 19:18
  • 1
    @Peter-ReinstateMonica -Wsign-compare works for me, but -Wall doesn't :/ Commented Oct 11, 2023 at 19:20
  • 1
    Let's enumerate all the integers i such that -1 <= i < 4 (in mathematical sense, not C sense). How many are those? My hand says {-1, 0, 1, 2, 3} makes 5 in total. Why do you expect 4 numbers to be printed? Commented Oct 11, 2023 at 19:38

2 Answers 2

3

Within the conditional expression of the for loop

 for (i = -1; i < sizeof(array) / sizeof(int); i++) {

the variable i having the signed type int is implicitly converted to the unsigned type size_t due to the usual arithmetic conversions because the expression sizeof(array) / sizeof(int) has the unsigned integer type size_t and the rank of the type size_t (that is usually an alias for the type unsigned long) is greater than the rank of the type int.

As a result the expression ( size_t )-1 (the variable i is set initially to -1) that is the left operand of the condition i < sizeof(array) / sizeof(int) becomes a very big unsigned value due to propagating the sign bit.

Try for example this call of printf

printf( "( size_t )-1 = %zu\n", ( size_t )-1 );

So the condition of the if statement evaluates to logical false.

You could write for example

 for ( i = -1; i < ( int )( sizeof(array) / sizeof(int) ); i++) {

to get the expected result - to execute the for loop.

Though in any case the loop will invoke undefined behavior because when i will be equal to ( int )( sizeof(array) / sizeof(int) ) - 1 the expression array[i+1] will try to access memory beyond the defined array.

It will be much better and correct to write

for ( size_t i = 0; i < sizeof(array) / sizeof(*array); i++) {
    printf("%d ", array[i]);
}
Sign up to request clarification or add additional context in comments.

Comments

2

Comparing signed and unsigned values can lead to surprising behaviour. You are effectively doing (size_t)i < sizeof(array) / sizeof(int), and (size_t)-1 is a huge number.

In this case, there's no reason to start with i = -1; this can be done correctly and more simply with i = 0, which avoids the problem at hand. (You attempted to loop once too many times anyway, and starting with i = 0 also fixed that.)

ALWAYS enable your compiler's warnings. With gcc or clang, I use -Wall -Wextra -pedantic. It would have caught this.

3 Comments

Add -Werror so you won't be tempted to use code that compiles with warnings.
I'm not tempted to ignore warnings.
Me neither, but I make the compiler force my hand with -Werror.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.