What happens amid array initialization in c?

Given that it is legal

uint8_t bytes[4] = { 1, 2, 3, 4 }; 

And this is not so:

 uint8_t bytes2[4]; bytes2 = { 1, 2, 3, 4 }; 

What does { 1, 2, 3, 4 } mean?

Suppose this is not an rvalue or lvalue value. Sweetheart preprocessor code that expands to something?

+5
source share
4 answers

{1,2,3,4} is a list of initializers, a specific syntax token that can only be used on the line where the array is declared.

This is regulated exclusively by the standard C syntax. There is no particular explanation; this is exactly how the language is defined. In C syntax, arrays cannot be assigned or copied using assignment.

However, you can avoid syntax restrictions in several ways to overwrite all values ​​at once. The easiest way is to create a temporary array and memcpy:

 uint8_t tmp[] = {5,6,7,8}; memcpy(bytes, tmp, sizeof bytes); 

Alternatively, use a compound literal:

 memcpy(bytes, (uint8_t[]){5,6,7,8}, sizeof bytes); 

If this makes sense for a particular application, you can also wrap an array in the structure to circumvent syntax limitations:

 typedef struct { uint8_t data [4]; } array_t; ... array_t bytes = { .data = {1,2,3,4} }; array_t tmp = { .data = {5,6,7,8} }; bytes = tmp; // works just fine, structs can be copied this way 
+7
source

Syntax like {1,2,3,4}; is called a parenthesized list of initializers; this is an initializer. It can only be used for initialization (for array type).

Citation C11 , chapter Β§6.7.9

  • P11

The initializer for the scalar must be a single expression,

[the array is not a scalar type, therefore not applicable to us]

  • P14

A character type array can be initialized with a character string literal or a UTF-8 literal string, optionally enclosed in curly braces.

[We do not use the string literal here, therefore, are also not applicable to us]

  • P16

Otherwise, an initializer for an object that has an aggregate or type of union must be enclosed in parentheses a list of initializers for elements or named elements.

[It concerns our interests]

and, P17,

Each list of <initializers> associated with a curly brace has a current object associated with it. When there is no designation, the subobjects of the current object are initialized in the order of the type of the current object: array elements in ascending order of substrings , member structure in the declaration order and first name of the union member. [....]

So, here the values ​​from the closed list of brackets are not tied directly to the array, they are used to initialize individual elements of the array.

OTOH, an array type, is not mutable lvalue, so it cannot be assigned. In other words, an array variable cannot be used as an LHS assignment operator.

To develop, from C11 , chapter Β§6.5.16

the assignment operator must have a mutable value of lvalue as its left operand.

+8
source

Initialization and purpose are fundamentally different things. As for the C language, you just have to admit the fact that they are different, but, of course, there is a technical reason why he defined this method:

On many systems, you may have a data segment in an executable file. This segment can be read / written and an initialized array can be specified, for example

 uint8_t foo[] = {1, 2, 3, 4}; // assume this has static storage duration 

the compiler may simply decide to output this exact sequence of bytes directly to your executable. Thus, without code, it performs the assignment; the data is already in memory when your program starts.


OTOH, arrays cannot be assigned (only their individual members). This is how C is defined, and it is sometimes unsuccessful.

+5
source

{1,2,3,4} is a list of initializers. It is used to indicate the initial value of an object with at least 4 elements, whether it be array elements or structure elements, including objects of nested objects.

You cannot use this syntax to assign values ​​to an array as follows:

 bytes2 = {1,2,3,4}; 

Since the syntax is not supported, and arrays are not lvalues.

You can use initializer lists as part of a C99 syntax called compound literals to create objects and use them as values ​​for assignment, return values, or function arguments:

 struct quad { int x, y, z, t; }; struct quad p; p = (struct quad){1,2,3,4}; 

You still cannot use this for arrays because they are not lvalues, but you can achieve the same effect when calling memcpy() :

 uint8_t bytes2[4]; memcpy(bytes2, (uint8_t[4]){1,2,3,4}, sizeof(bytes2)); 

This statement is compiled by clang as a single intel command, as can be seen on β†’>

+3
source

Source: https://habr.com/ru/post/1269519/


All Articles