“下面展示的Code 1和Code 2有什么区别?我在两种情况下都得到了相同的输出。内部是否有任何不同?”
Code 1
char test[30]="KEL";
strcat (test,"DATA");
代码 2
char test[]="KEL"
strcat (test,"DATA");
Code 1
char test[30]="KEL";
strcat (test,"DATA");
代码 2
char test[]="KEL"
strcat (test,"DATA");
test
将有 30 个字符的空间。"KEL"
和空终止符(如果我没记错的话,剩下的字符都将被初始化为零,感谢 chux)。连接 "DATA"
到它上面是良好定义的。"DATA"
连接到它上面时,你将超出缓冲区的边界。这是未定义的行为。test
的余数也被设置为零 - 在C语言中不存在部分初始化。 - chux - Reinstate Monica让我们从C标准开始。根据它(6.7.9 Initialization)
14个字符类型的数组可以通过字符字符串文字或UTF-8字符串文字进行初始化,可选地用大括号括起来。字符串文字的连续字节(包括终止空字符,如果有足够的空间或数组大小未知)将初始化数组的元素。
和
19初始化应按初始化程序列表顺序进行,为特定子对象提供的每个初始化程序都会覆盖同一子对象的先前列出的初始化程序;151)所有未明确初始化的子对象都将隐式初始化为具有静态存储期的对象。
这些引用如何应用于字符数组初始化?
在此代码片段中
char test[30]="KEL";
strcat (test,"DATA");
数组test
声明了30
个元素。数组的前四个元素通过字符串字面量中的元素显式初始化,可以表示为{'K','E','L','\0'}
。所有其他元素都像具有静态存储期的对象一样隐式初始化,即通过值'\0'
。
因此,在其声明后,数组test内部看起来像
{
'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");
strcat (test,"DATA");
这将导致覆盖数组以外的内存,程序会出现未定义的行为。
char test[30]="KEL";
在这种情况下,编译器在堆栈中分配了30个字节。只要最终字符串的大小不超过30个字节(包括空终止符),就可以使用strcat连接字符串。
char test[]="KEL"
代码1 char test[30]="KEL";
// 你不能输入超过30个字符的值,但少于30个是可以的。
代码2 char test[]="KEL"
//你可以自由输入任何大小的值。