0

可能重复:
为什么我没有收到“分段错误”?

为什么这段代码有效?如果第一个元素只包含第一个字符,那么其余字符存储在哪里?如果这是可能的,我们为什么不使用这种方法呢?

注意第 11 行:静态字符 c[1]。使用一个元素,您可以存储任意数量的字符。当稍后指向它时,我使用静态来使内存位置在函数之外保持活动状态。

#include <stdio.h>

void PutString( const char* pChar ){
   for( ; *pChar != 0; pChar++ )
   {
      putchar( *pChar );
   }
}

char* GetString(){
    static char c[1];
    int i = 0;
    do
    {
        c[i] = getchar();
    }while( c[i++] != '\n' );
    c[i] = '\0';
    return c;
}

void main(){
    PutString( "Enter some text: " );
    char* pChar = GetString();
    PutString( "You typed the following:\n" );
    PutString( pChar );
}
4

5 回答 5

2

C 不检查数组边界,因此不会引发错误。但是,第一个字符之后的字符将存储在程序未分配的内存中。如果字符串很短,这可能会起作用,但足够长的字符串会损坏足够的内存以使进程崩溃。

于 2012-11-04T20:15:52.463 回答
2

可以随心所欲地写:

char *bad = 0xABCDEF00;
bad[0] = 'A';

但你不应该。谁知道上面几行代码会做什么?在最好的情况下,你的程序会崩溃。在最坏的情况下,你已经损坏了内存,直到很久以后才会发现。(祝你好运追踪源头!)

要回答您的具体问题,它“不起作用”。其余字符直接存储在数组之后。

于 2012-11-04T20:16:24.433 回答
1

您只是非常(不)幸运,您没有覆盖其他一些数据结构。数组绝对不能存储你想要的尽可能多的字符——迟早你要么默默地破坏你的内存(在最坏的情况下),要么通过访问你的进程没有映射的内存来遇到段错误。它起作用的事实可能是因为编译器没有在您的c[1]. 只需尝试添加第二个数组,比如说static char d[1];在 之后c,然后尝试从中读取 - 你会看到 . 中的第二个字符c

于 2012-11-04T20:17:25.767 回答
1

C++ 不对数组进行边界检查。这是出于性能原因;检查每个数组索引以查看它是否超出范围会导致不可接受的运行时开销。避免开销一直是 C++ 的设计目标。

如果你想要边界检查,你应该使用std::vector它,它确实通过std::vector::at().

于 2012-11-04T20:18:07.787 回答
1

在这种情况下,行为是未定义的:根据编译器/内存的当前状态/ ...,它可能看起来运行良好,它可能会写入损坏的字符,或者它可能由于一个错误而崩溃。

链接Electric Fence或在valgrind中运行可能有助于在运行时发现此类错误。

于 2012-11-04T20:18:51.313 回答