最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c - Correct syntax for whole array initializaition - Stack Overflow

programmeradmin1浏览0评论

Why is the following an error and what is the correct syntax?

struct a {
    int b[4];
};

int c[4];
struct a a = {.b = &c};

Shouldn't a.b be of type int * or int[], why is it of type int?

(Note, that the declaration of struct a can't be changed.)

Why is the following an error and what is the correct syntax?

struct a {
    int b[4];
};

int c[4];
struct a a = {.b = &c};

Shouldn't a.b be of type int * or int[], why is it of type int?

(Note, that the declaration of struct a can't be changed.)

Share Improve this question edited Nov 28, 2024 at 10:35 Caulder asked Nov 28, 2024 at 10:02 CaulderCaulder 3561 silver badge11 bronze badges 11
  • You can't initialize one array from another unfortunately. a.b is of type int[4] which is different from int *. – interjay Commented Nov 28, 2024 at 10:32
  • "Shouldn't a.b be of type int * or int[], why is it of type int?" Yes, it is one of your 2 options. But you seem to think, that they are the same, which they are not. You use it as if it was int* but you defined it as int[]. And a.b is not of type int. Where do you get that idea from? – Gerhardh Commented Nov 28, 2024 at 10:41
  • @Gerhardh I got that idea from my compiler. – Caulder Commented Nov 28, 2024 at 10:45
  • You must provide an initializer list: struct a a = { .b={1, 2, 3, 4}}; You cannot initialize an array with a pointer (i.e. the address of another array). – Gerhardh Commented Nov 28, 2024 at 10:45
  • 1 @Gerhardh I appended an explanation about that to my posted answer. – Lundin Commented Nov 28, 2024 at 11:00
 |  Show 6 more comments

2 Answers 2

Reset to default 3

The C language is a bit weird since for historical reasons it does not allow initialization or assignment between two arrays. That's just how the language is defined.

C does however allow structs to be initialized/assigned from other structs of the same type. Even if they happen to contain an array. So you could do this:

struct a c = { .b = {1,2,3,4} };
...
struct a a = c;

Or otherwise skip initialization and use run-time assignment instead. Since we're dealing with arrays we can't use = but have to use memcpy:

int c[4] = {1,2,3,4};
struct a a;
memcpy(a.b, c, sizeof(a.b));

As for the reason for the peculiar compiler error:

warning: initialization of 'int' from 'int (*)[4]' makes integer from pointer without a cast [-Wint-conversion]

Initialization of arrays (or structs) is done by the compiler internally keeping track on the current object to initialize. When we type in a designated initializer .b, the compiler sets the current object to be initialized to the first item b[0] in the array b. And then expects a number of initializers with type int from there on. For each int we hand it in the initializer list, it will automatically shift current initialized object to the next one in the list, b[1], b[2] and so on.

If written properly that would look like .b = {1,2,3,4} but the braces are actually optional. What matters is the compiler keeping track of the current object. We could as well write sloppy code like .b = 1,2,3,4. Very bad practice but valid C.

Anyway, since the compiler expects an int but is given a pointer to array with &c, it raises a constraint violation diagnostic message. It expected an int but got a int (*)[4] and that is invalid C.

.b = something is fine as far as the syntax is concerned, the types just didn't match in case of .b = &c. The types are regulated by the constraints of the assignment operator. A compiler must give a diagnostic message whenever the code violates either the C syntax or the C constraints.

You are correct in your assessment: b should have type int * or int const * but you should drop the & from the initializer:

struct a {
    int *b;
};

int c[4];
struct a a = { .b = c };

Or equivalently:

struct a a = { c };
发布评论

评论列表(0)

  1. 暂无评论