начальное значение массива int в C - PullRequest
42 голосов
/ 12 сентября 2009

При объявлении массива в C следующим образом:

int array[10];

Каково начальное значение целых чисел ?? Я получаю разные результаты с разными компиляторами, и я хочу знать, имеет ли это какое-то отношение к компилятору или к ОС.

Ответы [ 8 ]

61 голосов
/ 12 сентября 2009

Если массив объявлен в функции, то значение не определено. int x[10]; в функции означает: взять в собственность область memroy размером 10-int без какой-либо инициализации. Если массив объявлен как глобальный или как static в функции, то все элементы инициализируются нулями, если они еще не инициализированы.

20 голосов
/ 12 сентября 2009

Как установлено стандартом, все глобальные и функциональные статические переменные автоматически инициализируются равными 0. Автоматические переменные не инициализируются.

int a[10];  // global - all elements are initialised to 0

void foo(void) {
    int b[10];    // automatic storage - contain junk
    static int c[10]; // static - initialised to 0
}

Однако рекомендуется всегда вручную инициализировать переменную функции независимо от ее класса хранения. Чтобы установить для всех элементов массива значение 0, вам просто нужно присвоить первому элементу массива значение 0 - для пропущенных элементов автоматически будет установлено значение 0:

int b[10] = {0};
11 голосов
/ 12 сентября 2009

Почему локальные функции (auto класс хранения) не инициализируются, когда все остальное?

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

С другой стороны, не auto объекты должны быть очищены только один раз. Кроме того, ОС в любом случае должна очищать выделенные страницы из соображений безопасности. Таким образом, дизайнерское решение здесь заключалось в том, чтобы указать нулевую инициализацию. Почему безопасность тоже не проблема со стеком? На самом деле это очищается, во-первых. Мусор, который вы видите, связан с более ранними примерами фреймов вызовов вашей собственной программы и библиотечного кода, который они вызвали.

Конечный результат - быстрый, эффективный для памяти код. Все преимущества сборки без единой боли. До того, как dmr изобрел C, "HLL", такие как ядра Basic и целые ОС, были в буквальном смысле реализованы как гигантские ассемблерные программы. (За некоторыми исключениями в таких местах, как IBM.)

7 голосов
/ 12 сентября 2009

Согласно стандарту С, 6.7.8 (примечание 10):

Если объект, который имеет автоматический срок хранения не инициализирован явно его значение неопределенный.

Так что это зависит от компилятора. В MSVC отладочные сборки будут инициализировать автоматические переменные с 0xcc, тогда как не отладочные сборки вообще не будут инициализировать эти переменные.

5 голосов
/ 12 сентября 2009

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

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

Чтобы попросить компилятор установить для вас массив равным нулю, вы можете написать его как:

int array[10] = {0};

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

4 голосов
/ 13 сентября 2009

В большинстве последних компиляторов (например, gcc / vc ++) частично инициализированные члены локального массива / структуры по умолчанию инициализируются нулями (int), NULL (строка char / char), 0.000000 (float / double).

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

int a[5] = {0,1,2};
printf("%d %d %d\n",*a, *(a+2), *(a+4));

struct s1
{
int i1;
int i2;
int i3;
char c;
char str[5];
};

struct s1 s11 = {1};
    printf("%d %d %d %c %s\n",s11.i1,s11.i2, s11.i3, s11.c, s11.str);
    if(!s11.c)
        printf("s11.c is null\n");
    if(!*(s11.str))
        printf("s11.str is null\n");

В gcc / vc ++ вывод должен быть:

0 2 0 1 0 0 0,000000 s11.c является нулевым s11.str равно нулю

3 голосов
/ 12 сентября 2009

Текст от http://www.cplusplus.com/doc/tutorial/arrays/

РЕЗЮМЕ:

Инициализация массивов. При объявлении регулярный массив локальной области видимости (в пределах функция, например), если мы не указать иначе, его элементы будут не может быть инициализирован в любое значение по умолчанию, поэтому их содержание будет неопределенный, пока мы не будем хранить какое-то значение в них. Элементы глобального и статические массивы, с другой стороны, являются автоматически инициализируется с их значения по умолчанию, которые для всех Основные типы это означает, что они заполнено нулями.

В обоих случаях, локальных и глобальных, когда мы объявляем массив, у нас есть возможность присвоить начальные значения каждому из его элементов заключая значения в фигурные скобки {}. Например:

int billy [5] = { 16, 2, 77, 40, 12071 };
0 голосов
/ 26 февраля 2019

Соответствующие разделы из стандарта С (акцент мой):

5.1.2 Среда исполнения

Все объекты со статическим хранилищем длительностью должны быть инициализированы (установить их начальные значения) перед запуском программы.

6.2.4 Длительность хранения объектов

Объект, идентификатор которого объявлен с внешней или внутренней связью или со статическим спецификатором класса хранения, имеет статическое хранилище длительность.

6.2.5 Типы

Массив и типы структур вместе называются агрегатными типами.

6.7.8 Инициализация

Если объект с автоматическим хранением длительностью явно не инициализирован , его значение является неопределенным , Если объект, который имеет статическое хранилище длительность , не инициализируется явно , , тогда :

  • если он имеет тип указателя, он инициализируется нулевым указателем ;
  • если он имеет арифметический тип, он инициализируется (положительным или беззнаковым) ноль ;
  • если это агрегат , каждый элемент инициализируется (рекурсивно) в соответствии с этими правилами;
  • если это объединение, первый именованный элемент инициализируется (рекурсивно) в соответствии с этими правилами.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...