C上的数组是否可变长度?

时间:2012-03-24 02:41:17

标签: c arrays memory-management gcc

我试图制作一个基于数组的线性列表,然后我编译了这个:

char size = 0;
char testarray[10];

int main() { 
    add('a'); add('b'); add('c');
    add('d'); add('e'); add('f');
    add('g'); add('h'); add('i');
    add('j'); add('k'); add('l');
    add('m'); add('n'); add('o');
    print();
    return 0;
} 

void add(char newchar) {
    testarray[++size] = newchar;
}

void print() {
    char i = 0;
    for (i = 0; i <= size; i++) {
        printf("%c ", testarray[i]);
    }
 }

gcc arraytest.c编译它,但数组运行正常。这是否意味着默认情况下数组是可变长度的?我认为这是一个仅限C99的功能。

它是在Gentoo(gcc version 4.5.3 (Gentoo 4.5.3-r2 p1.1, pie-0.4.7)和Ubuntu(gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)下编译的。

哦,这不是有点危险吗?

4 个答案:

答案 0 :(得分:7)

不,它们的大小不变。你只是写过数组的末尾并破坏其他一些内存。没有任何检查可以证明这一点。

答案 1 :(得分:5)


将C视为世界上最棒的汇编语言,它也是可移植的。它完全不同于专为内存安全而设计的语言。 (那将是大多数其他的。)

你可以回答这样的问题的一种方法(即“C实际上做什么”)是用cc -S ...进行编译并检查生成的汇编代码。即使您不熟悉机器语言,也可以说它没有调用或检查下标范围。

C实际上无法真正做到这一点,因为x[i]被定义为*(x + i),所以它确实是“高级汇编语言”就像他们说的那样。

答案 2 :(得分:4)

只要您在应用程序的分配范围内,就可以在任何地方使用指针/地址。继续走得太远,你要么丢弃你的程序,要么点击你分配的内存的边缘,并获得某种保护错误。运行时检查很昂贵,不管怎样都不想拥有它。

交换你的两个变量

char testarray[10];
char size = 0;

看看你跑的时候会发生什么......

然后这样做:

char size = 0;
char testarray[10];
char stuff[10];

在你开始向testarray添加东西之前,初始化东西,然后在你的东西打印出stuff []数组之后。你应该看到你的溢出。在C中,将非数组变量放在赋值列表中并且数组或数组最后,这是一个很好的规则,你有更好的调试机会。

答案 3 :(得分:2)

正如Vaugh所说,你只是“幸运”*因为数组中的内存是可写的。有可能出现分段错误。事实上,如果你稍微更改程序以便数组在堆栈中,那么通过valgrind运行它会向你发出大量的警告。

*“幸运”,因为程序没有崩溃。不幸的是......它会在以后发生。