Вопрос

Извините , если это вопрос новичка :( .

Фрагмент кода на языке Си.

int array[5];
int cnt;

for(cnt = 0; cnt <= 10; cnt+=1)
{
      array[cnt] = cnt;
}

Должно выдавать ошибку, верно?Нет!Работает отлично!Но почему это так?Похоже, что - в первой строке - определен массив размером более чем в два раза (11).Вы даже можете получить доступ к массиву [5-10] позже.И это сбивает меня с толку.Он перестает работать, когда вы определяете массив [4 или меньше] ...

Заранее благодарю.

Это было полезно?

Решение

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

Поведение вашего кода в соответствии со спецификацией языка C является неопределенный.Это означает, что он может сделать то, на что вы надеетесь, или это может привести к сбою вашего компьютера, или это может вызвать демоны вылетят у тебя из носа.

В отличие от языков более высокого уровня, таких как Java и C #, C доверяет вам и не выполняет явных проверок границ массивов.Предполагается, что вы должны быть ответственными и не выходить за границы массива.

Другие советы

Это "работает" только в том случае, если ваше определение "работает" является синонимом "еще не разбился".

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

"Но почему это так?"

Потому что таков уж C есть.

Границы массива не проверяются во время выполнения.

Это "Закон С".

Я просто хотел бы отметить, что все это действительно не определено.Ваш пример "работает" в этом конкретном примере, потому что обе переменные расположены в стеке.То есть адрес cnt находится чуть ниже конца массива.Когда cnt достигает cnt==5 массив инструкций[cnt]=cnt;записывается не в память, выделенную для массива, а сразу после него, где находится адрес cnt.Это просто удача, что это не изменяет ваш счетчик.Когда cnt> 5, памяти для удаления нет, и она просто записывается в "stack void" (не знаю подходящего слова).

еще один пример, иллюстрирующий это:

int main(int ac,char **av)
{
    int a[5];
    int cnt;
    int cnt2=3;

    for(cnt=0;cnt<7;cnt++) {
        a[cnt]=cnt;
        printf("%d %d %d\n", a[cnt], cnt, cnt2);
    }
}

выходной сигнал:

0 0 3
1 1 3
2 2 3
3 3 3
4 4 3
5 5 5
6 6 5

Последние две записи цикла перезаписывают данные стека после[] и могут привести к очень запутанным ошибкам.В этом случае cnt2 уничтожается.

Массивы в C не проверяются во время выполнения.Другими словами, вы можете "определить" массив размером N и с радостью получить доступ к концу привязки массива.Если вы перейдете к концу массива, то вы уничтожите память где-нибудь в стеке (или куче).

Как только вы где-то уничтожите память, ваша программа, скорее всего, выйдет из строя.Эти сбои может быть трудно отследить, потому что они могут произойти далеко от того места, где вы фактически пересекли конец массива.

Обычно, когда вы объявляете массивы на C, лучше всего использовать какую-то константу или #define для обозначения размера массива:

#define MAX_ELEMENTS 10
int array[MAX_ELEMENTS];
int cnt;
for(cnt = 0; cnt < MAX_ELEMENTS; cnt+=1) {
   array[cnt] = cnt;
}

Если вы пройдете мимо MAX_ELEMENTS при назначении массива, вы можете перезаписать значение cnt.Вы могли бы перезаписать какую-нибудь другую переменную.Все зависит от компилятора и структуры кода.Также обратите внимание на использование < войдите в цикл for.Массивы C основаны на 0, поэтому вы должны проверять, используя значение меньше, а не меньше или равно.

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

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

Зависит от того, как упакована память стека.Кроме того, он с радостью перезапишет эти значения и даже прочитает их, но, скорее всего, вы повреждаете стек.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top