Являются ли массивы переменной длины по умолчанию на C? - PullRequest
4 голосов
/ 24 марта 2012

Я пытался создать линейный список на основе массива, затем скомпилировал это:

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 ]

7 голосов
/ 24 марта 2012

Нет, они не переменного размера. Вы просто пишете за концом массива и забиваете какую-то другую память. Нет никаких проверок, чтобы сделать это очевидным.

5 голосов
/ 24 марта 2012
нет

Нет


Думайте о C как о лучшем языке ассемблера в мире, и он также переносим. Это совершенно не похоже на языки, разработанные для сохранения памяти. (Это было бы большинство других.)

Один из способов ответить на подобные вопросы (например, «что на самом деле делает C») - это скомпилировать с cc -S ... и проверить сгенерированный код сборки. Даже если вы не знакомы с машинным языком, вы, вероятно, можете сказать, что он не вызывает или не проверяет диапазон индекса.

C никогда не сможет этого сделать, как это происходит, потому что x[i] определен как *(x + i), так что на самом деле это «язык ассемблера высокого уровня» , как они говорят.

4 голосов
/ 24 марта 2012

Пока вы находитесь в пределах выделенного диапазона для вашего приложения, вы можете использовать указатели / адреса в любом месте. продолжайте идти достаточно далеко, и вы либо погасите свою программу, либо попадете на край выделенной памяти и получите какой-то сбой защиты. Проверка во время выполнения обходится дорого, в любом случае не хотелось бы этого.

поменяйте местами две переменные

char testarray[10];
char size = 0;

и посмотри, что произойдет, когда ты запустишь его ...

А затем сделайте это:

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

перед тем, как вы начнете добавлять вещи в testarray, инициализируйте вещи, а затем, выполнив вашу вещь, распечатайте массив stuff []. Вы должны увидеть ваше переполнение. В C это хорошее правило, чтобы сначала поместить переменные, не являющиеся массивами, в список назначений, а массив или массивы последними, у вас больше шансов на отладку.

2 голосов
/ 24 марта 2012

Как сказал Вог, вам просто "повезло" в том, что память за массивом доступна для записи.Существует вероятность ошибки сегментации.Фактически, если вы немного измените программу, чтобы массив находился в стеке, то запустите его через valgrind, и он выдаст вам множество предупреждений.

* «Удача» в том, что программа не аварийно завершилась.Не повезло в этом ... это будет позже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...