C: Должен ли я инициализировать массивы, используемые внутри функции?

avatar
the-powl
1 июля 2021 в 19:12
72
2
1

Во время отладки моей программы я заметил, что некоторые элементы моего 2D-массива содержат ненулевые значения.

float Ak[2][2];
Ak[0][0] = 1;
Ak[1][1] = 1;

Когда я запускаю этот код, Ak[0][0] и Ak[1][1] равны 1, как и ожидалось, но Ak[0][1] равно 1,081, что я на самом деле ожидал быть равным 0.

Возможно, это связано с тем, что массивы не инициализируются неявно. Но всегда ли это так? Должен ли я всегда инициализировать свои массивы, когда мне нужно определенное поведение, или есть случаи, когда компилятор делает это автоматически? Это зависит от компилятора?

И почти самый важный вопрос: Где указано это поведение? (Мне нужна цитата для моей диссертации)

Источник
Steve Summit
1 июля 2021 в 19:13
2

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

Tom Karzes
1 июля 2021 в 20:17
2

Локальные нестатические переменные не инициализированы. Локальные статические переменные неявно инициализируются нулем, как и нелокальные переменные.

Ответы (2)

avatar
Vlad from Moscow
1 июля 2021 в 19:38
1

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

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

Кажется, вы объявили свой массив внутри функции

float Ak[2][2];
Ak[0][0] = 1;
Ak[1][1] = 1;

Поэтому его элементы не инициализируются неявно.

Можно написать, например,

float Ak[2][2] =
{
    [0][0] = 1.0f, [1][1] = 1.0f 
};

В этом случае все элементы массива будут инициализированы. Элементы, не имеющие явного инициализатора, будут инициализированы нулями.

Вот демонстрационная программа.

#include <stdio.h>

int main(void) 
{
    float Ak[2][2] =
    {
        [0][0] = 1.0f, [1][1] = 1.0f 
    };

    printf( "Ak[0][0] = %f, Ak[0][1] %f, Ak[1][1] = %f\n", 
             Ak[0][0], Ak[0][1], Ak[1][1] );
    
    return 0;
}

Вывод программы:

Ak[0][0] = 1.000000, Ak[0][1] 0.000000, Ak[1][1] = 1.000000

В качестве альтернативы вы можете инициализировать свой массив также следующим образом

float Ak[2][2] =
{
    [0] = { [0] = 1.0f }, [1] = { [1] = 1.0f } 
};
avatar
dbush
1 июля 2021 в 19:15
4

Любая переменная (не только массивы), определенная локально, которая не является static или, более формально, с автоматической длительностью хранения, не инициализируется неявно. Те, которые определены в области файла или с помощью static, то есть те, у которых статическая продолжительность хранения, неявно инициализируются 0 или NULL.

Это указано в разделе 6.7.9p10 стандарта C:

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

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

И, конечно же, тот факт, что неинициализированная переменная равна 0, не означает, что она не содержит мусора.

Eric Postpischil
1 июля 2021 в 19:34
0

Кроме того, только потому, что это 0, не означает, что это 0! Неопределенный означает, что может быть 3, даже если было видно, что он равен 0.