3

I'm new to C programming and I'm struggling really hard to understand why this works

#include <stdio.h>


int main() {
    int l = -5;
    char arr[l];

    printf("content: %s; sizeof: %d\n", arr, sizeof(arr));
}

with output:

content: ; sizeof: -5

and this doesn't:

#include <stdio.h>


int main() {
    char arr[-5];

    printf("content: %s; sizeof: %d\n", arr, sizeof(arr));
}

with output:

name.c:6:10: error: size of array ‘arr’ is negative
    6 |     char arr[-5];
      |          ^~~

I was expecting an error also from the first example, but I really don't know what's happening here.

6
  • 1
    Format specifier for the result of sizeof (which is size_t) is %zu. This will clear one of the mysteries here. Commented Nov 29, 2021 at 18:21
  • oh, I see, thank you. By the way it appears like a huge number, still the problem hasn't been solved Commented Nov 29, 2021 at 18:23
  • I think l from char arr[l] is converted to size_t which is an unsigned type. For printing sizeof you need %zu to get correct output from printf Commented Nov 29, 2021 at 18:23
  • @bolov I just wonder why the literal -5 is not converted as well. Probably because it is a definition rather than an a statement. Commented Nov 29, 2021 at 18:24
  • 1
    Ah, probably because -5 is not a literal but rather an expression with unary - operator and literal 5 Commented Nov 29, 2021 at 18:30

1 Answer 1

5

Neither version of the program conforms to the C language specification (even after the format specifiers are corrected to properly match the size_t argument). But the two cases are semantically different, and they violate different provisions of the language specification.

Taking this one first:

    char arr[-5];

The expression -5 is an integer constant expression, so this is a declaration of an ordinary array (not a variable-length array). It is subject to paragraph 6.7.6.2/1 of the C17 language spec, which says, in part:

In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero.

(Emphasis added.)

That is part of a language constraint, which means that the compiler is obligated to emit a diagnostic message when it observes a violation. In principle, implementations are not required to reject code containing constraint violations, but if they accept such codes then the language does not define the results.

On the other hand, consider

    int l = -5;
    char arr[l];

Because l is not a constant expression (and would not be even if l were declared const), the provision discussed above does not apply, and, separately, arr is a variable-length array. This is subject to paragraph 6.7.6.2/5 of the spec, the relevant part requiring of the size expression that:

each time it is evaluated it shall have a value greater than zero

The program violates that provision, but it is a semantic rule, not a language constraint, so the compiler is not obligated to diagnose it, much less to reject the code. In the general case, the compiler cannot recognize or diagnose violations of this particular rule, though in principle, it could do so in this particular case. If it accepts the code then the runtime behavior is undefined.

Why this program emits -5 when you compile and run it with your particular C implementation on your particular hardware is not established by C. It might be specified by your implementation, or it might not. Small variations in the program or different versions of your C implementation might produce different results.

Overall, this is yet another example of C refusing to hold your hand. New coders and those used to interpreted languages and virtual machines seem often to have the expectation that some component of the system will inform them when they have written bad code. Sometimes it does, but other times it just does something with that bad code that might or might not resemble what the programmer had in mind. Effective programming in C requires attention to detail.

Sign up to request clarification or add additional context in comments.

2 Comments

"another example of C refusing to hold your hand." --> Yes, Random User, welcome to coding without training wheels.
Thank you very much for your explanation, it was really helpful! Also thanks for the "life lesson" about C, I knew it would be hard and i know that I did wrong years ago starting with Python.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.