如果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
缓冲区的有效大小。在我看来,引入此实现是为了避免问题的严重性

If
charres[SIZE3]堆栈上,它将包含随机/未定义的内容。
你永远不会知道在
res[SIZE3]
中是否会有一个零字节,因此
strcat
未定义


如果
charres[SIZE3]
是一个未初始化的全局,它将是全零,这将使它表现为一个空的c字符串,并且
strcat将是安全的(只要SIZE3足够大以满足您添加的内容)。

TL;DR是的


因为这是一个语言律师的问题,让我再加上我的两分钱

引用
C11
,第§7.24.3.1/2章(重点是我的)

strcat
函数附加由
s2
指向的字符串的副本(包括 终止空字符)
s1
初始字符所指向的字符串的末尾 of
s2
覆盖
s1
末尾的空字符[…]

根据定义,字符串空结尾,引用§7.1.1/1

字符串是以第一个null结尾的连续字符序列 字符。

因此,如果源
char
数组不是以null结尾的(即,不是字符串),
strcat()
很可能会在搜索调用的结尾时超出界限


根据你的问题,
charres[SIZE3]
是一个自动局部变量,将包含不确定的值,如果用作
strcat()
的目标,将调用UB。

我认为
strcat
在连接字符串之前开始搜索
res
字符串中的
null终止符,因此它是UB。@LPs UB到底是什么?这行不是
charres[SIZE3]={0}
initialize
res
to
15
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);