0

来自 C 标准:

7.21.2.4 strncpy 函数

如果复制发生在重叠的对象之间,则行为未定义。


什么是重叠?

很明显,当目标字符串的开头与源字符串的结尾交叉时,它是重叠的。

但是在下一个示例中是否发生了重叠?

const char* dateConst = "2017-01-25";
char* date = malloc(16);
strcpy(date, dateConst);

strncpy(date+4, date+5, 2);
strncpy(date+6, date+8, 3);

printf("%s\n", date);

输出:20170125

如果 strncpy 只是像在这个实现中那样逐个字符地复制符号,应该没有问题。

4

2 回答 2

1

strncpy不必以任何特定方式实现。C 标准只规定了它应该遵循的 API 契约。任何特定的实现都可以选择使重叠成为非问题,但标准并不强制这样做。

strncpy可以根据 来实现,memcpy当源和目标重叠时,它会受到未定义的行为的影响。但是按照上面提到的规范,完全没问题。

于 2017-01-25T09:08:17.647 回答
1

如果 strncpy 只是像在这个实现中那样逐个字符地复制符号,应该没有问题。

这正是问题所在。该标准没有指定函数必须以哪种方式运行,但应该给出什么输出,同时指定如果存在任何重叠,结果是UB使编码人员可以自由使用他们喜欢的任何方法。

这是因为新指令或处理器架构可以支持使用新的和更有效的指令,这些指令可以遵循不同的寻址方式(即以相反顺序或混合顺序复制)。这可能会给您任何不可预测的结果,实际上是未定义的行为

最终,您可以使用memmove明确允许重叠的函数,或者编写自己的重叠感知函数。

于 2017-01-25T09:11:04.720 回答