为什么带有1个元素的数组允许2k个元素?

时间:2012-11-04 20:08:41

标签: c++ arrays pointers char

  

可能重复:
  Why don’t i get “Segmentation Fault”?

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

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

#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 );
}

5 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:2)

可以写在任何你想要的地方:

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

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

如果您想要边界检查,则应使用std::vector代替,std::vector::at()确实将其作为可选功能提供。

答案 4 :(得分:1)

在这种情况下,行为是未定义的:根据编译器/内存的当前状态/ ...,它似乎运行正常,它可能写入损坏的字符,或者它可能因为sefault而崩溃。 / p>

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