in C, expression
int *a = {};
compiles ok.
Why I can assign {} to a int pointer.
What {} mains, and what's in variable a.
When in debug mode, why the variable a is NULL.
How to expain and understand this expression? and why it compiles?
in C, expression
int *a = {};
compiles ok.
Why I can assign {} to a int pointer.
What {} mains, and what's in variable a.
When in debug mode, why the variable a is NULL.
How to expain and understand this expression? and why it compiles?
int *a = {};
This will only compile in a C23 compiler. It is using the new "empty initilizer" available in C23, proposed in N2900. (e.g. if you change the value of --std
or simply switch to an older version of GCC you'll get error: empty scalar initializer
). Note however that it's been a feature of C++ for a while, and also supported in C compilers as an extension, so depending on how you're compiling and what you're compiling with you might be able to use that syntax in an older compiler or a lower level of C standard.
What does it do? It sets a
to a null pointer.
It's almost-equivalent to writing this:
int *a;
memset(&a, 0, sizeof(a));
which is a way to create a pointer with all-bits-zero, which on almost every system in existence will be a null pointer. But {} guarantees a null pointer instead of an all-bits-zero one.
You might be used to writing = {0}
for structures and arrays, it's intended to replace that syntax whilst also working on scalar primitives such as int
and int*
.
It is a GCC extension which was introduced as a result of another extension - zero-length arrays. If you have zero-length arrays, you need to have an empty initializer list too (inr a[0] = {};
). As a consequence, GCC developers had to decide what to do if an empty list is used to initialize a pointer. They decided to assign NULL to this pointer in this case (more precisely a single element initializer list {0}
).
It is not covered by the C standard until C23.
Before the C23 Standard
int *a = {};
such an initialization is not C standard (though some compilers can have their own language extensions). According to the C grammar before the C23 Standard the initialization is defined like
1 initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
As it can be seen, empty braces are not allowed.
In C23 such an initialization is allowed
1 braced-initializer:
{ }
{ initializer-list }
{ initializer-list , }
and (C23, 6.7.10 Initialization)
11 If an object that has automatic storage duration is initialized with an empty initializer, its value is the same as the initialization of a static storage duration object. Otherwise, if an object that has automatic storage duration is not initialized explicitly, its representation is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, or is initialized with an empty initializer, then default initialization:
— if it has pointer type, it is initialized to a null pointer;
...
So in C23 in this declaration
int *a = {};
the pointer a
is initialized as a null pointer.
Compilers that have their own language extensions also initialize the pointer a
as a null pointer before the C23 Standard follwoing the C++ Standard initialization where (for example C++14 Standard., 8.5.4 List-initialization)
(3.9) — Otherwise, if the initializer list has no elements, the object is value-initialized.
and (8.5 Initializers)
8 To value-initialize an object of type T means:
... (8.4) — otherwise, the object is zero-initialized
and at last
6 To zero-initialize an object or reference of type T means:
(6.1) — if T is a scalar type (3.9), the object is initialized to the value obtained by converting the integer literal 0 (zero) to T;
Relative to pointers it means initializating them as null poingters because in C and C++ Standards an integer constant with the value 0 is a null pointer constant:
The C Standard
3 An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. 67) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
and the C++ Standard
1 A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type. Such a conversion is called a null pointer conversion. Two null pointer values of the same type shall compare equal. The conversion of a null pointer constant to a pointer to cv-qualified type is a single conversion, and not the sequence of a pointer conversion followed by a qualification conversion (4.4). A null pointer constant of integral type can be converted to a prvalue of type std::nullptr_t. [ Note: The resulting prvalue is not a null pointer value. — end note ].
int *a = {};
is not defined by the current C standard because{}
is supposed to contain a non-empty list of initializers, per C 2018 6.7.9 1. It is expected to be defined in a forthcoming C standard.To the extent it is meaningful in C, it means “Initialize
a
from this list,” and then there is nothing in the list, so the default initialization is applied. Compilers that accept this code will typically interpret it this way. The default initialization for a pointer is to set it to a null pointer value, per C 2018 6.7.9 10.