char四[4]=“四”;这个语句的正确语义是什么?

时间:2022-11-20 22:27:38
int main(void)
{
    char four[4] = "four";
    return 0;
}

When compiled as a C++ program, G++ reports

当编译为c++程序时,G++报告

xxx.cpp: In function int main():

xxx。cpp:在函数int main()中:

xxx.cpp:3: error: initializer-string for array of chars is too long

xxx。错误:chars数组的initializer-string太长了

When compiled a a C program, GCC reports no error.

当编译一个C程序时,GCC报告没有错误。

It appears to me, that the assignment is correctly copying all 4 bytes into the variable, as I expected.

在我看来,作业正确地将所有4个字节复制到变量中,正如我所期望的那样。

So my question boils down to.....

所以我的问题归结为……

Is the observed behavior in C correct or am I touching an undefined behavior somewhere, or is it something else altogether?

在C中观察到的行为是正确的,还是我在某个地方碰到了一个未定义的行为,抑或是其他的行为?

4 个解决方案

#1


22  

Short answer: your code is valid C, but not valid C++.

简短的回答:您的代码是有效的C,但不是有效的c++。

Long Aswer:

长反潜战:

"four" is actually 5 characters long - there is a \0 added there for you. In section 6.7.8 Initialization, paragraph 13, the C standard says:

“四”实际上是5个字符长——有一个为你添加的\0。在第6.7.8节的初始化第13段中,C标准说:

An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

字符类型的数组可以由字符串字面量来初始化,也可以选择用括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,包括终止空字符)初始化数组的元素。

So the \0 is just ignored in your program when it is compiled as C. C++ is treating it differently. In fact, this particular case is called out explicitly in the C++ spec (Section 8.5.2 Character arrays, paragraph 2):

所以当你的程序编译为C++时,你的程序会忽略\0。事实上,在c++规范(第8.5.2节字符数组,第2段)中明确指出了这个特殊的情况:

There shall not be more initializers than there are array elements. [ Example:

初始化器的数量不能超过数组元素的数量。(例子:

char cv[4] = "asdf";  // error

is ill-formed since there is no space for the implied trailing ’\0’. — end example ]

由于没有隐含的结尾“\0”的空间,所以是不正确的。——最后的例子)

#2


2  

The string "four" actually contains five bytes: the four letters plus a zero byte (\0) as a string terminator. It's been a while since I've written C or C++, but I would guess the C compiler is silently ignoring it for whatever reason.

字符串“4”实际上包含五个字节:四个字母加上一个0字节(\0)作为字符串终止符。我写C或c++已经有一段时间了,但是我猜C编译器出于某种原因正在悄悄地忽略它。

#3


2  

Better would be

更好的将

char four[] = "four";

#4


1  

What you're seeing is a difference between C and C++. C allows you to have extra initializers, which are ignored. C++ prohibits this -- if you specify a size for a string (or array) it must be large enough to accommodate all the initializers (including the NUL terminator, in the case of a string), or the code is ill-formed (standardese for "it's not allowed -- expect the compiler to reject it").

您看到的是C和c++之间的区别。C允许您有额外的初始化器,它们被忽略。c++禁止这个——如果你指定一个字符串的大小(或数组),它必须大到足以容纳所有的初始化(包括NUL终结者,在一个字符串的情况下),或不规范的代码(standardese“这是不允许的——希望编译器拒绝”)。

#1


22  

Short answer: your code is valid C, but not valid C++.

简短的回答:您的代码是有效的C,但不是有效的c++。

Long Aswer:

长反潜战:

"four" is actually 5 characters long - there is a \0 added there for you. In section 6.7.8 Initialization, paragraph 13, the C standard says:

“四”实际上是5个字符长——有一个为你添加的\0。在第6.7.8节的初始化第13段中,C标准说:

An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

字符类型的数组可以由字符串字面量来初始化,也可以选择用括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,包括终止空字符)初始化数组的元素。

So the \0 is just ignored in your program when it is compiled as C. C++ is treating it differently. In fact, this particular case is called out explicitly in the C++ spec (Section 8.5.2 Character arrays, paragraph 2):

所以当你的程序编译为C++时,你的程序会忽略\0。事实上,在c++规范(第8.5.2节字符数组,第2段)中明确指出了这个特殊的情况:

There shall not be more initializers than there are array elements. [ Example:

初始化器的数量不能超过数组元素的数量。(例子:

char cv[4] = "asdf";  // error

is ill-formed since there is no space for the implied trailing ’\0’. — end example ]

由于没有隐含的结尾“\0”的空间,所以是不正确的。——最后的例子)

#2


2  

The string "four" actually contains five bytes: the four letters plus a zero byte (\0) as a string terminator. It's been a while since I've written C or C++, but I would guess the C compiler is silently ignoring it for whatever reason.

字符串“4”实际上包含五个字节:四个字母加上一个0字节(\0)作为字符串终止符。我写C或c++已经有一段时间了,但是我猜C编译器出于某种原因正在悄悄地忽略它。

#3


2  

Better would be

更好的将

char four[] = "four";

#4


1  

What you're seeing is a difference between C and C++. C allows you to have extra initializers, which are ignored. C++ prohibits this -- if you specify a size for a string (or array) it must be large enough to accommodate all the initializers (including the NUL terminator, in the case of a string), or the code is ill-formed (standardese for "it's not allowed -- expect the compiler to reject it").

您看到的是C和c++之间的区别。C允许您有额外的初始化器,它们被忽略。c++禁止这个——如果你指定一个字符串的大小(或数组),它必须大到足以容纳所有的初始化(包括NUL终结者,在一个字符串的情况下),或不规范的代码(standardese“这是不允许的——希望编译器拒绝”)。