Является ли хорошей практикой группировать связанные константы, используя структуры в C? - PullRequest
1 голос
/ 07 апреля 2020

Мне было интересно, будет ли хорошей идеей использовать структуры в качестве псевдо-пространств имен (а-ля C ++) для группировки констант, которые функционально или концептуально связаны друг с другом.

static const struct {

    const unsigned int START;
    const unsigned int END;

} COUNTER = {.START = 1, .END = 100};

Есть ли недостатки к этому? Если нет, то является ли избыточным (или, может быть, даже неудобным), чтобы экземпляр структуры и его члены были объявлены как const? Где должна указываться постоянство этих значений?

Ответы [ 2 ]

2 голосов
/ 07 апреля 2020

Полезно ли группировать связанные константы, используя структуры в C?

Это основано на мнениях. Если это работает для вас, сделайте это.

Я бы так не поступил, я C. Вместо этого я использую #define

Как:

#define GROUPNAME_NAME

, поэтому в вашем случае я бы сделал

#define COUNTER_START 1
#define COUNTER_END 100

В C ++ я бы сделал:

const unsigned int COUNTER_START = 1;
const unsigned int COUNTER_END = 100;

Разница между C и C ++ связана с различиями в спецификации языка.

2 голосов
/ 07 апреля 2020

Мне было интересно, будет ли хорошей идеей использовать структуры в качестве псевдо-пространств имен

Ну, это МОЖЕТ быть хорошей идеей. Это по сути не плохо. Аргумент против состоит в том, что если вы чувствуете, что вам нужны пространства имен, то, скорее всего, C - это неправильный язык. Но его можно использовать таким образом, и иногда он используется таким образом.

Где должна указываться постоянство этих значений?

В целом достаточно объявить вся структура как постоянная. Но будьте осторожны с указателями. Этот код действителен и выведет «42»:

int x = 5;

const struct {
        int *p;
} S = {.p = &x };

int main()
{
        *(S.p) = 42;
        printf("%d\n", x);
}

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

Для пояснения, указатель p будет объявлен так же, как int * const p, что означает, что вы не можете изменить сам указатель, но чтобы защитить данные, на которые он указывает, вам нужно const int *p. Чтобы получить оба, используйте const int * const p, но если структура объявлена ​​как const, вы получите один из них «бесплатно», поэтому const int *p достаточно, чтобы получить оба.

И если вы рассмотрите указатели к указателям, хорошо, обдумайте это в течение долгого времени и проверьте его, чтобы убедиться, что он работает так, как вы хотите.

Из комментариев:

Почему бы не перечислить?

Поскольку это недопустимо:

enum S {a = 5};
enum Y {a = 6};

Компилятор скажет Вы, что a уже определено. Поэтому enums не подходит для эмуляции пространств имен. Также нельзя использовать перечисления для нецелых чисел.

...