Допустимо ли инициализировать массив целочисленного типа внутри структуры до NULL? - PullRequest
0 голосов
/ 20 июня 2020

Предположим, у меня есть эта структура:

typedef struct foo
{
bool bar[4];
}foo;

, а затем я хочу создать массив этой структуры:

foo foo_arr[] = {
{{true, true, false, true}}, 
{{false, true, false, true}}, 
{NULL}
};

Действительна ли инициализация структуры foo_arr[2] ? А если нет, то как правильно указать такой массив на NULL?

  • Требование: структура должна быть размещена в стеке.

Ответы [ 2 ]

3 голосов
/ 20 июня 2020

Таким же образом вы не можете использовать:

int arr[] = {1, 2, NULL};

, вы не можете установить элемент, ожидающий тип foo на NULL, для этого вам нужно использовать массив указателей на foo:

#include <stdio.h>
#include <stdbool.h>

typedef struct foo
{
    bool bar[4];
} foo;

int main(void)
{
    foo foo_arr[] = {{{true, true, false, true}}, {{false, true, false, true}}};
    foo *foo_ap[] = {&foo_arr[0], &foo_arr[1], NULL};

    for (int i = 0; foo_ap[i] != NULL; i++)
    {
        foo *foo_ptr = foo_ap[i];

        printf("%d %d %d %d\n",
                foo_ptr->bar[0],
                foo_ptr->bar[1],
                foo_ptr->bar[2],
                foo_ptr->bar[3]);
    }
    return 0;
}

Вывод:

1 1 0 1
0 1 0 1
2 голосов
/ 20 июня 2020

" Можно ли сделать точку массива, выделенного глобальным стеком, на NULL? "

" Является ли инициализация (инициализация) структуры в foo_arr[2] действителен?"

Нет, это не в порядке и недействительно. По крайней мере, не так, как вы (C нарушение синтаксиса с {NULL} - это должно быть {{NULL}} для компиляции).

typedef struct foo
{
   bool bar[4];
} foo;

foo foo_arr[] = {
    {{true, true, false, true}}, 
    {{false, true, false, true}}, 
    {{NULL}}
};

Действительно, при некоторых требованиях это инициализирует все элементы от bar до 0, но давайте начнем с начала.

Почему вы хотите использовать NULL? NULL используется для сравнения и установки указателей , а не объектов данных. bar не является массивом указателей.

У меня действительно был подобный вопрос, через несколько месяцев go:

Это зависит от реализации, допустимо ли использовать NULL для инициализации объектов данных в 0, поскольку макрос NULL либо расширяется до 0 или (void*) 0. Если это последнее, реализация должна указать, что произойдет, если вы назначите указатель на void целочисленному типу.

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

Источник: C18, 6.3.2.3/6

Итак, если любой,

  1. NULL расширяется до 0 в вашей конкретной реализации c , или
  2. Реализация определяет преобразования из указателей в целые числа (преобразование из (void*) 0 в объект данных),

это действительно инициализирует все элементы bar в третья структура равна 0, по следующим причинам:

Во-первых, {{NULL}} устанавливает первый bool объект в массиве bar в третьей структуре массива foo_arr на 0.

Неявный ly он также инициализирует все следующие три объекта bool как 0, потому что:

"Если в списке, заключенном в фигурные скобки, меньше инициализаторов, чем элементов или членов агрегата, или меньше символов в строковом литерале, используемом для инициализации массива известного размера, чем количество элементов в массиве, оставшаяся часть агрегата должна быть инициализирована неявно так же, как объекты, которые имеют stati c продолжительность хранения. "

Источник: C18, 6.7.9 / 20

Это означает, что если вы инициализируете первый bool объект, он автоматически инициализирует все остальные.

" Если нет, как правильно указать такой массив на NULL? "

Как сказано выше, а не на NULL, на 0 или false. Массив (элементы) никуда не указывает . Это не указатели! Как указано выше, вы можете просто использовать {{0}} или {{false}}:

typedef struct foo
{
   bool bar[4];
} foo;

foo foo_arr[] = {
    {{true, true, false, true}}, 
    {{false, true, false, true}}, 
    {{0}};
};
...