代码:

int a[4]={1,2,3,4};

(以上可以运行,不会报错)

int a[4];

a[4]={1,2,3,4};

(以上会报错)


int a = 0;

这叫初始化

int a; a = 0;

这叫赋值

虽然长得像,但完全是两种东西。

数组只能初始化,没办法赋值。


定义的时候赋值叫初始化……和赋值不是一回事儿


这样可以,先用typeof把匿名字面量转换成数组对应类型,再memcpy。不过应该没什么地方用得上吧。。。

#include &
#include &

int main(void)
{
int a[3];
memcpy(a, (typeof(a)){1,2,3}, sizeof(a));

printf("%d
", a[0]);

return 0;
}

如果是结构体,连memcpy也不用,可以直接用加了typeof的匿名变数来赋值。

typeof似乎是gcc的扩展语法,gcc以外的环境不知道能不能用了。

#include &
#include &

struct {
int a;
float b;
} t;
int main(void)
{
t = (typeof(t)){1, 2.0};
printf("%f
", t.b);
return 0;
}


在modern cpp中可以后赋值的, 见: https://godbolt.org/z/N7odMG


因为C语言标准一直没支持这么写,定义的时候那个叫做初始化初值,不叫赋值。C语言一致没支持数组的直接赋值,但是支持结构体的直接赋值,所以要实在想直接赋值,可以这么干,虽然很麻烦:

typedef struct int_array_4_
{
int a[4];
} int_array_4;

int main(int argc, char *argv[])
{
int_array_4 a;
int *a_a = (int *)a;

a = (int_array_4){{1, 2, 3, 4}};

printf("%d
", a_a[0]);

return 0;
}


数组可以通过字面量初始化

但不能通过字面量赋值

赋值必须基于索引/下标


a[4]是什么?

int a[4];

这个语句定义了一个含 4 个 int 型元素的数组。

那请问 a 的数据类型是什么?

int[4]

就是包含了 4 个 int 型元素的数组。

其中还可以通过对 a 解除引用(也就是 *a )来访问 a[0] ,数组 a 的第一个元素。也就是说, a 可以看作指向 a[0] 的一个常指针。

也就只有在定义的时候, a[4] 是包含 4 个元素的数组。

a[4] = 233;

这个语句为 a[4] 这个元素赋值为 233 。就不像上面的定义是指一个有 4 个元素的数组。

a[0] 是数组 a 的第一个元素,那么 a[4] 就是第 5 个……

等等,数组 a 不是只有 4 个元素吗……

C 语言可不管这个。在 C 语言中, a[4] 就相当于 *(a+4) 。 a+4 是什么?就是 a 指向的地址,往后数 4 个 int 占的位元组数,数到的地址。再一解除引用,就得到了那个地址里的数据。对 a[1] , a[2] 和 a[3] 是同样的。 C 语言只管找地址,数组越界什么的是不会管的。

C++ 抄 C 的时候就把这个抄过来了(怎么能说是抄呢

是的,你在用 a[4] 的时候用上了别人家的内存。(手动滑稽)

然后是 = { 1 , 2 , 3 , 4 } 的问题。

= 是干什么用的?

当然是赋值用的啦。

一定义就赋值的操作,又叫做初始化。

初始化时等号右边可以是一些奇奇怪怪的东西。

int a[4] = { 1, 2, 3, 4 };
char str[7] = "vczhnb";
struct student
{
char name[16];
int age;

} vczh = { "Victor Chen" , 666 };

每个数组或结构体只有这一次愉快赋值的机会哦!过期不候!再往后只能一个一个元素或成员的赋值了。

自己想想定义完 C 风格字元串 str 之后你又写了句 str = "lzgnb"; 试图修改 str 的内容。

然而这时 str 已经算是个常指针了,给一个常指针赋值你是在想桃吃。(逃

写出 a[4] = { 1 , 2 , 3 , 4 }; 就是更NM离谱,把一个 initializer-list 赋给一个 int ?你这辈子都别想再吃桃了。(不知道 initializer-list 的请自行百度)

以上种种原因导致定义之后的数组和结构体都不能再用等号直接赋值了(直接把结构体赋给结构体还是可以的)

至于有些什么简便的赋值方法,其它回答已经给出,比如 memcpy() 或专门针对 C 风格字元串的 strcpy() 之类的。题主可以自己去了解一下。


cppreference上有明确的说明,见图

而且退一万步讲,a[4]指的是数组中的一个元素,类型是int,当然不能把int数组类型赋值给int类型


不一定要在一行内赋值,你的问题有几个

第一,你没有理解下标a[4]是指下标为4的那个元素,但是你理解为了a这个数组,造成这个误解可能是因为,申明数组的时候是写a[4]。

第二,可以赋值,可以了解一下memset和memcpy两个函数

第三,对于int a[4]的理解,等你学会了动态分配内存malloc应该会对这个问题有一个更深一点的想法


首先

int a[4] = {1,2,3,4};

应该相当于

int a[4];

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

而不是a[4]={1,2,3,4}

但是这个格式仍然是不允许的。因为规定如此,这个只能用作初始化。


a[4]指的是a数组中的第5个int元素,你不能对它赋值另外一个数组。如果先声明了需要用for或者指针来挨个赋值才能覆盖整个数组。


语法问题有什么纠结的?


首先你的前一段代码也会报错,因为你把右花括弧}打成了右方括弧]。

为什么后一段代码会报错,因为a[4]是int,你却对它赋一个不能转换成int类型的值。

另外,a[4]是数组的第五个元素,你访问还越界了,虽然这一般不会引发报错。


int a[4]; // 声明了一个变数a,变数类型为 int[4]

a[4]={1,2,3,4}; // 通过数组下标给数组元素赋值,
// a[4]是一个下标访问表达式,
// 表达式结果是一个左值,它的类型是int,
// 把一个数组字面量赋值给int类型的变数,
// 是不可能成功的。
// 另外由于a只有4个元素,下标4越界了。


c和c++就是没有直接提供数组的赋值语法。原因大概是c++初始化即赋值的概念出现的时候语言的作者脑子不清楚。

不排除未来会直接提供数组赋值语法。

目前对无需析构的类型的数组,进行延迟初始化的技巧有

  1. placement new的数组版本,执行的是构造语义:

int a[4];

new (a[0]) int[4] { 1, 2, 3, 4 };

2. 强转std::array赋值,执行的是先构造临时std::array再赋值(覆盖)到a,对于元素为简单类型int来说,编译器会省略构造临时array的步奏直接赋值到a上

((std::array&) a[0]) = {1, 2, 3, 4}

对于第二种方法保证不会出错,不像第一种方法只能对无需析构的元素类型使用


哥们,语法搞错了吧。定义时的中括弧是表示长度,赋值时中括弧是取下标。


int a[4]={5,6,7,8}

中4为数组长度,在这时a[4]相当于整个数组,在这时你设定整个数组为{5,6,7,8}是没有问题的

a[4]={5,6,7,8}

中4为数组下标。首先a数组长度为4。其中所有元素下标分别为0,1,2,3。这里的a[4]就出现了第一个问题下标越界。a中根本没有下标为4的元素。

其次a[4]现在的意义是a数组中下标为4的元素。根据定义这个元素为int类型。而后面的{5,6,7,8}并不是一个int类型,这就是第二个问题,类型错误。

如果您想对初始化完成的数组进行赋值那么只能一个一个元素赋值.


推荐阅读:
相关文章