Question Details

No question body available.

Tags

c language-lawyer undefined-behavior c99 variable-length-array

Answers (2)

April 17, 2026 Score: 4 Rep: 236,017 Quality: Medium Completeness: 100%

First, the behavior of int array[static 0] is not defined except that a conforming C implementation must issue a diagnostic message for it. This is because C 1999 6.7.5.2 1, which is in a Constraints section for array declarators, says:

… If the expression is a constant expression, it shall have a value greater than zero…

Thus, [static 0] violates this constraint. Since it is in a Constraints section, the C implementation is required to issue a diagnostic message, and the behavior is otherwise undefined.

That answers the second part of question 1 in the post:

  1. Does the C99 standard define any behavior for [static 0], or is a zero-length static array parameter itself already undefined/unspecified?

Now, suppose we ignore the constraint violation above. What is next? The following speaks to the title question:

Is passing NULL valid when array parameter uses [static 0] in C99?

and the first part of question 1 and question 2:

  1. If the static N constraint is vacuously satisfied when N == 0, does that make foo(0, NULL) fully defined behavior?

For these, the behavior is not defined because C 1999 6.7.5.3 7 says (bold added):

… If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

6.2.5 20 tells us (bold added):

… An array type describes a contiguously allocated nonempty set of objects with a particular member object type,…

Therefore, the pointer must point to an array. Due to the static 0, the array must have at least zero elements, but, due to the definition, all arrays have more than zero elements. So the pointer must point to a place where there is at least one element.

My guess would be this was not well considered by the committee, and if they had considered it, then pointing to “zero elements” might have been defined, possibly allowing a null pointer, possibly not.

Question 3 and the following code sample from the post present a different question:

  1. Does passing a VLA-based bound (i.e., [static len] where len is a runtime variable equal to 0) change the analysis compared to a compile-time constant [static 0]?
void foo(sizet len, int array[static len])
{
}

Yes, this changes the analysis because now another rule also applies. 6.7.5.2 5 says:

… If the size is an expression that is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by *; otherwise, each time it is evaluated it shall have a value greater than zero.

“Function prototype scope” is when a function is declared but not defined, as in void foo(sizet len, int array[static len]);. So we do not have function prototype scope here. With the function definition, the declaration is in block scope. Therefore, each time len is evaluated (in its role as the array size), it shall have a value greater than zero, or the behavior is not defined.

Is the array size evaluated when the function is called? The standard is not clear on this. The nominal array declaration int array[static len] is automatically “adjusted” to make array a pointer, but the standard does not explicitly say where this adjustment occurs, and different compilers have treated it differently.

Thus, it is conceivable that a C implementation that does not evaluate the size of the array when the function is called would not violate this rule. Nonetheless, the rules above about pointing to an array still apply; the argument passed to foo must point to an array.

April 17, 2026 Score: 2 Rep: 790,299 Quality: Low Completeness: 20%

When the size is 0, the requirement becomes

provide access to the first element of an array with at least 0 elements

All arrays have at least 0 elements, so "with at least 0 elements" is effectively redundant, so it can be interpreted as

provide access to the first element of an array

A null pointer doesn't provide access to any elements of an array, so it's not valid there.

Another clause may preclude actually accessing any elements of the array when size is 0, but it still has to point to an array.