下面显示的代码1和代码2之间有什么区别。在这两种情况下,我都是相同的。内部有什么不同吗?
代码1
char test[30]="KEL";
strcat (test,"DATA");
代码2
char test[]="KEL"
strcat (test,"DATA");
答案 0 :(得分:6)
在您的第一个代码示例中,test
将有30个字符的空格
前4个将是字符串"KEL"
+ nul终结符(如果我的内存服务,其余的也将初始化为0,感谢chux)。将"DATA"
连接到它是明确定义的。
在第二个样本中,它只有4个空格,因为缓冲区的长度是从字符串文字推导出来的。当您将"DATA"
连接到它时,您将超出缓冲区的边缘进行写入。这是未定义的行为。
如果标准显式未定义行为,那么编译器和运行时的实现可以做任何事情。你的程序会崩溃。或者它可以运行险恶的代码。它也可以出现,就像你的情况一样。但这不是你可以依赖的东西。
答案 1 :(得分:2)
让我们从C标准开始。根据它(6.7.9初始化)
14字符串数组可以用字符串初始化 文字或UTF-8字符串文字,可选择用大括号括起来。 字符串文字的连续字节(包括终止空值) 字符,如果有空间或数组的大小未知) 初始化数组的元素。
和
19初始化应在初始化程序列表顺序中进行,每个顺序 初始化程序为特定的子对象提供覆盖任何子对象 以前列出的同一子对象的初始值设定项; 151)全部 未初始化的子对象应初始化 隐含地与具有静态存储持续时间的对象相同。
如何将这些引号应用于字符数组初始化?
在此代码段中
char test[30]="KEL";
strcat (test,"DATA");
数组test
被声明为具有30
个元素。数组的前四个元素由字符串文字的元素显式初始化,可以表示为{ 'K', 'E', 'L', '\0' }
。所有其他元素都隐式初始化为具有静态存储持续时间值'\0'
的对象。
所以在声明内部的数组测试内部看起来像是
{
'K', 'E', 'L', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0'
}
在第二段代码中
char test[]="KEL"
strcat (test,"DATA");
声明了一个未知大小的数组,其大小根据初始值设定项的数量计算。由于字符串文字有四个字符{ 'K', 'E', 'L', '\0' }
,因此数组将具有完全相同的四个字符。
在第一个代码段中,您可以更改值为'\0'
的数组元素。例如,你可以写
test[3] = 'D';
test[4] = 'A';
test[5] = 'T';
test[6] = 'A';
,数组看起来像
{
'K', 'E', 'L', 'D', 'A', 'T', 'A', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0'
}
结果它将包含字符串"KELDATA"
。而不是带有赋值的几个语句,编写
strcat (test,"DATA");
并获得相同的结果。
然而,第二个代码片段呢?因为它被认为没有任何"免费"除了由字符串文字"KEL"
初始化的元素之外的元素。所以你可以改变的只是他的四个要素。您不能将新数据附加到存储在数组中的字符串文字。你只能覆盖它们。
因此这句话
strcat (test,"DATA");
将导致覆盖数组之外的内存,并且程序将具有未定义的行为。
答案 2 :(得分:1)
char test[30]="KEL";
在这种情况下,编译器在堆栈中分配30个字节。只要最终字符串的大小不超过30个字节(包括空终止符),就可以使用strcat连接字符串。
char test[]="KEL"
但是,在这种情况下,编译器本身决定为给定的字符串分配足够的内存。它是3个字节加上' \ 0'(空终止符)所以没有足够的空间来容纳另一个字符。
尝试编写超出编译器分配的内容,正如StoryTeller已经说明的那样,未定义的行为,这意味着程序可能正确执行或可能会崩溃。或者可以两次做。未定义的行为也是非常特定于编译器的属性。 gcc,clang或任何其他编译器编译的完全相同的源代码可能会产生不同的结果。
注意:字符类型(char)的大小为1个字节。
答案 3 :(得分:-1)
代码1 char test[30]="KEL";
//不允许输入大于30个字符但小于30个字符的值。
代码2 char test[]="KEL"
//免费提供您无需输入任何固定大小的值。