如果strcat函数中的目标字符串不是以null结尾的,这是未定义的行为吗?
以下程序如果strcat函数中的目标字符串不是以null结尾的,这是未定义的行为吗?,c,string,language-lawyer,strcat,C,String,Language Lawyer,Strcat,以下程序 // Code has taken from http://ideone.com/AXClWb #include <stdio.h> #include <string.h> #define SIZE1 5 #define SIZE2 10 #define SIZE3 15 int main(void){ char a[SIZE1] = "Hello"; char b[SIZE2] = " World"; char res[SIZE3]
// Code has taken from http://ideone.com/AXClWb
#include <stdio.h>
#include <string.h>
#define SIZE1 5
#define SIZE2 10
#define SIZE3 15
int main(void){
char a[SIZE1] = "Hello";
char b[SIZE2] = " World";
char res[SIZE3] = {0};
for (int i=0 ; i<SIZE1 ; i++){
res[i] = a[i];
}
strcat(res, b);
printf("The new string is: %s\n",res);
return 0;
}
被替换为
char res[SIZE3];
standard是否也明确说明了目标字符串要以null结尾?如果将
res
保持未初始化状态,则在将a
复制到res
(for循环中)之后,res
中没有NUL终止符。因此,如果目标字符串不包含NUL字节,strcat()
的行为是未定义的
基本上,strcat()
要求它的两个参数都是字符串(即两者都必须包含终止的NUL字节)。否则,它就是。这
从strcat()的描述中可以明显看出:
strcat函数附加s2指向的字符串的副本
(包括终止的空字符)到字符串的末尾
由s1指向。s2的初始字符覆盖空值
s1末尾的字符
(强调我的)。我想明确地说
描述
函数的作用是:将src字符串追加到dest字符串,覆盖dest结尾的终止空字节('\0'),然后添加一个终止空字节。字符串不能重叠,dest字符串必须有足够的空间来显示结果。如果dest不够大,则程序行为是不可预测的;缓冲区溢出是攻击安全程序的最常用途径
分阶段矿井
顺便说一句,我认为在连接新字符串之前,
strcat
开始在dest字符串中搜索null终止符
,因此它显然是UB,因为dest
字符串具有自动存储
在建议的守则中
for (int i=0 ; i<SIZE1 ; i++){
res[i] = a[i];
}
运行时约束
2设m表示输入到时的值s1max-strnlen_s(s1,s1max)
strcat\s
我们可以看到,
strlen\u s
总是返回dest
缓冲区的有效大小。在我看来,引入此实现是为了避免问题的严重性 Ifcharres[SIZE3]代码>在堆栈上,它将包含随机/未定义的内容。
你永远不会知道在res[SIZE3]
中是否会有一个零字节,因此是,strcat
未定义
如果charres[SIZE3]
是一个未初始化的全局,它将是全零,这将使它表现为一个空的c字符串,并且strcat将是安全的(只要SIZE3足够大以满足您添加的内容)。TL;DR是的
因为这是一个语言律师的问题,让我再加上我的两分钱
引用C11
,第§7.24.3.1/2章(重点是我的)
strcat
函数附加由s2
指向的字符串的副本(包括
终止空字符)到s1
初始字符所指向的字符串的末尾
ofs2
覆盖s1
末尾的空字符[…]
根据定义,字符串以空结尾,引用§7.1.1/1
字符串是以第一个null结尾的连续字符序列
字符。
因此,如果源char
数组不是以null结尾的(即,不是字符串),strcat()
很可能会在搜索调用的结尾时超出界限
根据你的问题,charres[SIZE3]
是一个自动局部变量,将包含不确定的值,如果用作strcat()
的目标,将调用UB。我认为strcat
在连接字符串之前开始搜索res
字符串中的null终止符,因此它是UB。@LPs UB到底是什么?这行不是charres[SIZE3]={0}
initializeres
to15
ZERO's?@Michi读了另一个问题:OP想知道char-res[SIZE3]是否代码>相反。@LPs我注意到它迟到了。这是我的另一个问题。@Groo:我发现自己很难想到许多定义为strcat
的用例。strcpy的一种变体,它接受目标缓冲区的“开始”和“过去一次”指针,并返回尾随零的位置(如果已写入)或目标的过去一次指针(如果已满)似乎更有用。A
不会复制到res
,它的b
以null结尾。我说的是在for循环中进行的复制,其中5个字节被复制到res
,没有NUL终止符。因此,后续的strcat()
将导致UB。因此5到14之间的其他字节将被取消初始化。
。这行是什么意思charres[SIZE3]={0}
?@Michi这个问题的意思是:如果我使用charres[SIZE3]代码>相反?我专注于代码本身:))这行charres[SIZE3]={0}是什么意思代码>?该死的你是对的…哦错过了LoL抱歉:)@Michi恰巧发生了,不用担心,让我们清理一下,好吗?我不知道为什么我会这样想a不一定是空终止的,但标准明确地说它是空终止的。在问这个问题之前,我应该先搜索一下。顺便说一句,@haccks有时我们所需要的只是一双额外的眼睛来填补空白。很乐意帮忙,先生。:)
for (int i=0 ; i<SIZE1 ; i++){
res[i] = a[i];
}
#define _ _STDC_WANT_LIB_EXT1_ _ 1
#include <string.h>
errno_t strcat_s(char * restrict s1,
rsize_t s1max,
const char * restrict s2);
char *strcat(char * restrict s1,const char * restrict s2);