Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple 0-length arrays have the same address?

Tags:

c

gcc

The following code prints out same address for both a and b using GCC (not tested with other compilers):

#include <stdio.h>

void show() {
    {
        static char a[0];
        printf("%p\n", a);
    }
    {
        static char b[0];
        printf("%p\n", b);
    }
}

int main() {
    show();
}

My question is does C standard allow multiple variables to have a same address or this is just an extension of GCC?

like image 538
so61pi Avatar asked Mar 19 '17 05:03

so61pi


People also ask

Can you have an array of size 0?

Although the size of a zero-length array is zero, an array member of this kind may increase the size of the enclosing type as a result of tail padding. The offset of a zero-length array member from the beginning of the enclosing structure is the same as the offset of an array with one or more elements of the same type.

Can an array have zero length Java?

Java allows creating an array of size zero. If the number of elements in a Java array is zero, the array is said to be empty. In this case you will not be able to store any element in the array; therefore the array will be empty.


2 Answers

The paragraph C11 6.7.6.2p1 says:

Constraints

  1. 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.

As your program violates a shall (0 is not greater than zero), the program would have undefined behaviour, except that in this case it appears within the constraints section. As the section 4 Conformance says

4 Conformance

  1. In this International Standard, ''shall'' is to be interpreted as a requirement on an implementation or on a program; conversely, ''shall not'' is to be interpreted as a prohibition.

  2. If a ''shall'' or ''shall not'' requirement that appears outside of a constraint or runtime- constraint is violated, the behavior is undefined. Undefined behavior is otherwise indicated in this International Standard by the words ''undefined behavior'' or by the omission of any explicit definition of behavior. There is no difference in emphasis among these three; they all describe ''behavior that is undefined''.

Also, the 5.1.1.3p1 says:

  1. A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. Diagnostic messages need not be produced in other circumstances. [9])

With footnote saying:

9) The intent is that an implementation should identify the nature of, and where possible localize, each violation. Of course, an implementation is free to produce any number of diagnostics as long as a valid program is still correctly translated. It may also successfully translate an invalid program.


Thus

  • C11 does not have arrays of size 0.

  • The presence of such arrays are a constraint violation

  • However, GCC allows zero-size arrays as an extension

  • A conforming C implementation must produce a diagnostics message upon such use.

  • That GCC compiles this one with default settings without outputting a diagnostics message even when -std=c11 is set makes gcc -std=c11 a non-conforming implementation.

  • The GCC documentation says that:

    [...] to obtain all the diagnostics required by the standard, you should also specify -pedantic (or -pedantic-errors if you want them to be errors rather than warnings).

  • Thus to use GCC to compile in such a manner that it conforms to say C11 standard, you must explicitly use at least gcc -std=c11 -pedantic; and then you will get:

    zerosizearray.c:5:21: warning: ISO C forbids zero-size array ‘a’ [-Wpedantic]
           static char a[0];
    
  • However, GCC will still compile your program, even if it is an incorrect program (unless you use -pedantic-errors); in such case naturally none of the requirements of the standard will apply.

Since the C standard does not really allow objects of size zero (if I read correctly, a struct definition must also have at least one member and so forth), and it is more of that that distinct objects must occupy distinct space in memory where the distinct addresses for objects come from; the standard doesn't specify anything about addresses of objects of size 0.

like image 151

In Standard C, zero-size array is not allowed.

If you're compile it with -pedantic option using gcc. It will give warning, saying:

zero.c:3:6: warning: ISO C forbids zero-size array 'a' [->pedantic]

like image 42
msc Avatar answered Sep 28 '22 10:09

msc