почему в структуре невозможно иметь члены stati c? - PullRequest
2 голосов
/ 27 мая 2020

Сначала из этого:

static struct foo1 { //private struct, just for this file
    int a;
};

int main (void) {
    struct foo1 a = {10};
    return 0;
}

номер вопроса 1

Я получаю предупреждение:

warning: useless storage class specifier in empty declaration
 };

Что это значит ? Почему static означает "бесполезный указатель класса хранилища"? В другом контексте (stati c local var in function или global stati c, который я хотел применить для struct foo1, это сработает).

вопрос номер 2

#include <stdbool.h>
static struct s_t{ //private struct (for this file only) 
    static bool is_there = false; // defaul (pre-defined) value for all instances
    int value;
};

int main (void) {}

Почему невозможно иметь stati c, предопределенное значение для всех переменных типа struct s_t в c? Я просто хотел смоделировать ту же функциональность, что и в функции static local var -> сохранить значение при нескольких вызовах, в этом смысле я хотел иметь один член (bool is_there в данном случае), который сохранить значение для каждой переменной типа struct foo1 (его экземпляр). Так почему это невозможно?

номер вопроса 3

Кроме того, может ли кто-нибудь объяснить ошибку (в более общем смысле) из нее:

error: expected specifier-qualifier-list before ‘static’

EDIT: из комментариев , Я не очень понимаю концепцию класса хранилища, знаю только из asm, есть data/text/bss segments, значит ли это, что static var имеет адрес в read-only части памяти? Или какова концепция storage class в c, связанная с asm?

Ответы [ 4 ]

3 голосов
/ 27 мая 2020
  1. Потому что static struct foo1 { ... - это просто определение структуры, а не переменная. Вы должны добавить static при объявлении экземпляра структуры. Я предпочитаю этот стиль:

    typedef struct  { 
        int a;
    }foo_t;
    
    static foo_t a = {10};
    
  2. Потому что C просто не имеет переменных-членов stati c, как это есть в C ++. В C довольно бесполезно добавлять спецификаторы хранилища или типа к одному члену структуры. Вместо этого поместите его в выделенные переменные.

  3. TL; DR это просто не имеет никакого смысла в вашем синтаксисе, поскольку у вас не может быть static. Если вас не очень интересует языковая грамматика, в этом нет ничего другого.

    static - это спецификатор класса хранения и const et c - это квалификаторы типа и int et c - это спецификатор типа . Термин спецификатор-квалификатор список происходит от формальной C грамматики структур, которую не очень интересно читать, если вы не создаете компилятор. При объявлении члена структуры у вас есть два варианта (C17 6.7.2.1):

    specifier-qualifier-list:
       type-specifier specifier-qualifier-list(opt)
       type-qualifier specifier-qualifier-list(opt)
    

    static не соответствует ни тому, ни другому, будучи спецификатором класса хранилища, поэтому компилятор говорит: « что! это не список спецификаторов-спецификаторов, где я ожидал найти один, где он? "

    (И да, он рекурсивный, поэтому у вас может быть несколько спецификаторов или квалификаторов типа, таких как const long const const int value;. Потому что C означает Сумасшедший.)

2 голосов
/ 27 мая 2020
static struct foo1 { //private struct, just for this file
        int a;
    };

Спецификатор объявления static применяется только к объявлениям объектов или функций, но не к определениям типов. Все, что вы делаете в этом операторе, - это создаете тип struct foo1. Если бы вы написали что-то вроде

static struct foo1 {
  int a;
} foo;

, тогда был бы объявлен объект foo static.

Если вы объявите тип в файле .c , он будет виден только в этом .c файле. Единственный способ сделать этот тип видимым для нескольких файлов .c - это объявить его в заголовке, а #include этот заголовок в каждом файле, который в нем нуждается.

Почему невозможно иметь stati c, предопределенное значение для всех переменных типа struct s_t в c?

Потому что типы C struct просто не так сложны - они просто способ определения элемент данных с несколькими атрибутами. Язык не предоставляет возможности иметь члены, общие для всех экземпляров типа.

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

2 голосов
/ 27 мая 2020

, поскольку структура подобна типу или объекту, когда вы объявляете член stati c в C, это будет выглядеть так:

static int a = 0;

В этом случае «int» похож на объявленный вами тип структуры, поэтому, если вы хотите создать член структуры stati c, просто сделайте следующее:

static s_t a;
0 голосов
/ 27 мая 2020

Что ж, совершенно очевидно, что вы получите предупреждение. Причина проста! Вы пытаетесь назначить класс хранилища определению struct . Однако классы хранения применимы к объявлениям переменных. Таким образом, вы получаете подсказку. Если вы по-прежнему используете sh класс хранения static, то вы можете сделать это с любой переменной, предпочтительно с любым экземпляром структуры.

...