插入数组时出现意外的空字符行为

问题描述 投票:0回答:2
#include <stdio.h>
#include <string.h>

void f(char s1[], const char s2[], int i, int j) {
    if (i >= 0 && j >= 0) {
        s1[i] = s2[j];
        f(s1, s2, i + 1, j - 1);
    }
}

int main() {
    char s1[5] = {'\0'}, s2[] = "hello";
    f(s1, s2, 0, (int)strlen(s2) - 1);
    printf(" %s \n", s1);
    return 0;
}

你好, 这段代码的打印结果是 olleh,但我预计代码会给出错误,因为在 for 循环期间空字符被覆盖,为什么会发生这种情况?

arrays c string
2个回答
0
投票

…我预计代码会出错…

这种期望是不正确的。当

printf
被传递时,对于
%s
转换,一个不包含空字符的数组,则该行为不是由 C 标准定义的。

没有任何内容表明计算机会出错。 C 标准中没有关于行为的规范

通常会发生的情况是,

printf
将继续检查数组末尾之外的内存并打印找到的内容,直到找到零字节为止。
s1
数组后面可能有一个零字节,因此
printf
立即停止。然而,其他行为也是可能的。
printf
可能打印了您没有看到的其他字符,因为它们没有可见的效果,例如空格或制表符或某些控制字符。在其他情况下,数组之外可能还有其他字符,并且
printf
可能会打印这些字符。或者,在优化过程中,编译器可能会以产生其他效果的方式转换您的程序。


0
投票

如果您尝试使用

%s
打印,并且传递的不是以 null 结尾的字符串,它将调用未定义的行为。

但是在您的情况下,

char s1[5] = {'\0'}
用零填充所有数组,因此如果
strlen(s2) < sizeof(s1)
s
s2
函数范围中的
main
)此代码将正常工作。

如果

sizeof(s2) >= sizeof(s1)
它将调用未定义的行为:

  • 你会写在arraut范围之外
    strlen(s2) > sizeof(s1)
  • 如果
    strlen(s2) >= sizeof(s1)
  • ,您将把非空终止字符串传递给 printf

这段代码的打印结果是 olleh,但我希望代码给出一个 错误,因为在 for 循环期间空字符被覆盖,为什么 会发生这种事吗?

覆盖第一个字符并不重要,因为如果按照初始化方式初始化数组,则数组将被清零。问题是您没有空间容纳空终止字符。它调用 UB。 UB 不必以任何特定方式表达自己。该代码可能工作正常、出现段错误、转移您所有的钱或其他东西。

© www.soinside.com 2019 - 2024. All rights reserved.