使用strcpy()时,目标字符串是否需要比源字符串大一个元素?

时间:2017-06-30 16:40:21

标签: c strcpy

请考虑此代码段(为简洁起见,简化语法)。

void simple (char *bar) {
    char MyArray[12];
    strcpy(MyArray, bar);
}

我的导师说 MyArray 最多可以复制来自 bar 的12个元素,但是从我的#&# 39;我读过,MyArray只能存储11个字符,因为它最后需要空字符。因此,如果 bar 的接收值为12或更大,则会发生缓冲区溢出。我的导师说,只有收到的 bar 值才会发生这种情况 是13或更高。谁对吗?如果你能引用一个可靠的消息来源我会说服他。我很感激。

5 个答案:

答案 0 :(得分:4)

定义char创建一个12 char [12]的数组,可用于存储字符串。由于C中的字符串是空终止的,因此其中一个字符需要能够在字符串的末尾存储空字节。

因此strcpy类型的变量可以包含最多11个字符的字符串。尝试使用strncpy复制长度为12或更长的字符串,如示例所示,将溢出数组的边界。

如果您使用strncpy(MyArray, bar, 12); ,如下所示:

MyArray

这不会溢出缓冲区,因为它最多可复制12个字符。但是,如果复制了12个字符,则表示该字符串不是以空值终止的,因此在技术上不是字符串。然后尝试在$HOME/.aws/config上使用期望空终止字符串的任何其他字符串函数将读取数组的末尾。

答案 1 :(得分:0)

这很难说,因为你的问题措辞有些令人困惑,但我认为你是对的,而你的导师是错的。

给出代码

void simple(char *bar) {
    char MyArray[12];
    strcpy(MyArray, bar);
}

如果传入的bar指向一个包含11个或更少字符的字符串,则有效字符串将被复制到MyArray,没有缓冲区溢出。但是如果字符串长度为12(或更多)字符,那么就会有缓冲区溢出,因为strcpy也会复制第13个字符,终止空字符。

之前您曾问过strncpy。鉴于代码

void simple2(char *bar) {
    char MyArray[12];
    strncpy(MyArray, bar, 12);
}

如果传入的bar指向11个或更少字符的字符串,则有效字符串将被复制到MyArray。但如果字符串长度为12个字符,我们就会遇到不同的问题。 strncpy将复制12个字符并停止,这意味着它不会复制终止空字符。不存在缓冲区溢出,但MyArray仍然不会包含有效字符串。

另外,你要求一个可靠的来源。我写了C FAQ list - 你认为这可信吗? : - )

答案 2 :(得分:0)

  

我的导师说MyArray最多可以复制来自栏的12个元素

更准确地说,数组MyArray最多可容纳数组bar的12个元素。否则将尝试访问阵列之外的内存。

所以事实上你的导师是对的。

声明数组MyArray只有12个元素

char MyArray[12];
  

但是从我读过的内容来看,MyArray只能存储11个字符,因为   它最后需要空字符

终止零也是一个角色。函数strcpy复制源字符串中的所有字符,包括源字符串中存在的终止零。

  

因此,如果bar的接收值为12或更大,则缓冲区溢出   会发生

在这种情况下,神奇数字12意味着什么?它是数组bar中的字符数,还是存储在数组栏中的字符串的长度(用作参数的转换为指向其第一个元素的指针)?

如果数字12表示存储在数组bar中的字符串的大小,则函数strcpy将尝试复制数组的所有字符,包括终止零,在本例中为数组{ {1}}必须声明为有13个元素。

MyArray

但是,如果数字12表示数组char MyArray[13]; 中的元素数(用作函数的参数)并且它包含一个字符串,那么字符串的长度显然小于12.所以数组MyArray可以接受源数组的所有字符,包括终止零。

所以混淆的原因是你没有得出一个共同的结论,数字12表示它是源字符串的长度还是源数组的大小。

在第一种情况下,确实存在未定义的行为。

在第二种情况下,如果源数组包含一个字符串,那么代码将是格式良好的。

答案 3 :(得分:0)

正确使用strncpy将是:

options

这只是输入一个终止空字符,无论void simple(char *bar) { char MyArray[12]; strncpy(MyArray, bar, sizeof(MyArray)-1); MyArray[sizeof(MyArray)-1]= '\0'; } 是否能够这样做。

答案 4 :(得分:0)

char数组与字符串相似,但不一样。

在C中,

  

string 是由第一个空字符终止并包含第一个空字符的连续字符序列。 C11dr§7.1.11

void simple (char *bar) {
    char MyArray[12];
    strcpy(MyArray, bar);
}
  

我的导师说MyArray最多可以复制12个元素,

这是正确的:MyArray[]最多可以接收12个字符。

strcpy()将内存从bar复制到数组MyArray[]并继续,直到它复制空字符。如果尝试复制多于12个字符(12个字符包括空字符),则结果为未定义行为UB)。

  

MyArray只能存储11个字符

不完全。 MyArray[]可以存储12个字符。要将该数据视为字符串空字符必须是其中之一12.当解释为字符串时,该字符串包含所有字符最多为空字符。它还包括 null chracter MyArray[]的每个元素都可以是'x',但是该内存不会是字符串,因为它缺少空字符。

  

因此,如果接收到的bar值为12或更大,则会发生缓冲区溢出。

不完全。如果strcpy()尝试在MyArray[]之外写入,则结果未定义。可能发生缓冲区溢出。程序可能会停止等。结果未定义。它是未定义的行为

  

我的导师说,只有当bar的收到价值为13或更高时,才会发生这种情况。

bar是一个指针 - 它可能没有“值13”。 bar可能指向字符串的内存。 字符串包含其终止空字符,因此字符串可以包含12个非空字符和最终空字符,总共13个字符。 MyArray[]不足以存储该字符串的副本。

  

谁是对的?

我怀疑脱离是“bar是13”的不精确含义。我看到教练报告的不正确。