Есть ли разница между инициализацией структуры с помощью {0} или {'\ 0'}? - PullRequest
0 голосов
/ 02 сентября 2018

Коллега по работе рекомендовал инициализировать структуру с {'\0'} вместо {0}, потому что он объяснил, что 0 считается int, таким образом, по крайней мере 4 байта. Поэтому, если структура не кратна 4, инициализация структуры 0 может оставить некоторые байты не инициализированными 0, в то время как \0 является символом ASCII байта размера 1, он инициализирует структуру в ноль независимо от ее размер.

При этом я почти никогда не видел инициализацию с использованием {'\0'}, в то время как я видел множество инициализаций с использованием {0}.

У меня вопрос: достаточно ли инициализации структуры с помощью {0}? Достаточно ли этого, потому что большинство компиляторов автоматически дополняют байты, не кратные 4, нулями, или это происходит из-за того, что это делает C?

Ответы [ 2 ]

0 голосов
/ 02 сентября 2018

Нет, разницы нет.

Для одного, '\0' не является «одним байтом»; в Си символьные константы имеют тип int, поэтому '\0' и 0 эквивалентны на 100% в каждом контексте. (Вы можете проверить это с помощью sizeof: и sizeof 0, и sizeof '\0' приведут к одному и тому же значению, обычно 4 или 8.)

Другая причина объясняется в правилах инициализации C (в C99 это 6.7.8 Инициализация ):

[...]

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

  2. Каждый заключенный в скобки список инициализаторов имеет связанный текущий объект . Когда нет обозначения присутствуют, подобъекты текущего объекта инициализируются в порядке типу текущего объекта: элементы массива в порядке возрастания индекса, структура члены в порядке объявления, и первый названный член союза. [...]

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

Если вы напишите

struct foo { double x; };
struct foo var = { 0 };

затем 0 (первое значение инициализатора, тип int) используется для инициализации первого поля структуры (x, тип double). Это как если бы вы написали double x = 0. В результате значение 0 неявно преобразуется из int в double и сохраняется в переменной.

Кроме того, если инициализаторов меньше, чем элементов структуры или массива, это правило срабатывает:

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

Так как же неявная инициализация работает со статическими объектами?

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

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

Это означает, что все неинициализированные в явном виде члены массива или структуры неявно установлены на 0.

0 голосов
/ 02 сентября 2018

Да, достаточно инициализировать структуру с {0}. Поймите, компилятор не назначает структуру памяти на основе инициализации. Структура, не зависящая от того, заполнена ли она каким-либо значением или нет, всегда будет требовать одинаковой памяти.

например.

#include <stdio.h>

struct A {
    char a;
};

struct B {
    int b;
};

int main(void) {
    struct A b = {'\0'};
    struct A c = {0};
    printf("%zu %zu\n",sizeof(b),sizeof(c));

    struct B ab = {'\0'};
    struct B ac = {0};
    printf("%zu %zu\n",sizeof(ab),sizeof(ac));

    return 0;
}

Ответы всегда будут одинаковыми, независимо от того, как вы их назначите.

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