首页 > 解决方案 > 为什么这个程序没有段错误?

问题描述

通常,这个问题可能会以积极的方式表达,成为重复问题俱乐部的下一个成员——希望这个不是。我写了一个简单的程序来反转 C 中的字符串。这里是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    char arr[4] = "TEST";
    char rev[2];

    int j = 0;
    for(int i = 0; i < 4; i++) {
        j = 4 - i - 1;
        rev[j] = arr[i]; 
    }

    printf("%s\n",rev);
}

当我定义char arrchar rev成为 4 号时,一切正常。当我忽略arr尺寸时,我会得到意想不到的重复输出,例如“TSTTST”。当我定义rev为 2 个字符的数组时,我没有收到段错误,但在循环中我试图访问它的第三个和第四个元素。据我相对有限的理解告诉我,访问长度为 2 的数组中的第三个元素应该是段错误,对吧?那为什么不呢?

编辑:

有趣的是,当我像这样离开循环时

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    char arr[4] = "TEST";
    char rev[2] = "00";

    printf("%s\n",rev);
}

它打印“00TEST”。这里发生了什么?某种溢出?我什至重新启动了终端,重新编译并再次运行。

编辑2:

我已经意识到这确实是重复的。但是,大多数建议的重复项都提到了 C++,而事实并非如此。我认为对于新的 C 程序员来说,这是一个学习和理解未定义行为的好问题。一方面,我不知道越界访问数组并不总是会导致 SEGFAULT。此外,我了解到我必须自己终止字符串文字,我错误地认为这是自动完成的。这部分是错误的:它是自动添加的-C99 标准 (TC3) 在6.4.5 字符串文字中说,在翻译阶段 7 中添加了终止空值。根据这个答案 and the answers for this question, char arrays are also null-terminated, but this is only safe if the array has the correct length (string length + 1 for null-terminator).

标签: c

解决方案


char rev[2] assigns a memory of size 2*sizeof(char) with variable/pointer rev. You are accessing memory not allocated to the pointer. It may or may not cause errors.

It might appear to work fine, but it isn't very safe at all. By writing data outside the allocated block of memory you are overwriting some data you shouldn't. This is one of the greatest causes of segfaults and other memory errors, and what you're observing with it appearing to work in this short program is what makes it so difficult to hunt down the root cause.

When you do rev[2] or rev[3] you are accessing rev + 2 and rev + 3 addresses which are not allocated to rev pointer. Since its a small program and there is nothing there, it's not causing any errors.

In respect to edit:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    char arr[4] = "TEST";
    char rev[2] = "00";

    printf("%s\n",rev);
}

%s prints till null is encountered, the size you have assigned of the arr and rev doesn't allow for null to be there, try changing values as follow:

    char arr[5] = "TEST";
    char rev[3] = "00";

The program will work as intended as in arr there will be TEST\0 and rev will be rev\0 where \0 is null character in C.

Give this article a read, it'll solve most of your queries.


推荐阅读