Является ли typedef спецификатором класса хранения?

Я пробовал следующий код

#include <stdio.h>

int main(void)
{
    typedef static int sint;
    sint i = 10;

    return 0;
}

и нажмите следующую ошибку:

error: multiple storage classes in declaration specifiers

Когда я ссылался на спецификацию C99, я узнал, что typedef является storage class.

6.7.1 Storage-class specifiers

Syntax

storage-class-specifier:
    typedef
    extern
    static
    auto
    register

Constraints: At most, one storage-class specifier may be 
             given in the declaration specifiers in a declaration

Semantics: The typedef specifier is called a ‘‘storage-class specifier’’ 
           for syntactic convenience only; 

Единственное объяснение, которое я смог найти (основанный на некотором интернет-поиске и перекрестке, ссылающийся на различные разделы в спецификации C99) был syntactic convenience only to make the grammar simpler.

Я ищу какое-то обоснование/объяснение того, как имя типа может иметь спецификатор класса хранения?

Не имеет смысла иметь такой код, как typedef static int sint;?

или Где я ошибаюсь?!

Ответы

Ответ 1

Да, typedef - спецификатор класса хранения, который вы нашли в стандарте. Частично это грамматическое удобство, но преднамеренно, что вы можете либо иметь typedef, либо один из более "очевидных" спецификаторов класса хранения.

Объявление typedef создает псевдоним для типа.

В объявлении static int x; тип x равен int. static не имеет ничего общего с типом.

(Считаем, что если вы берете адрес x, &x имеет тип int*. int *y = &x; будет законным, как и static int *z = &x, но этот последний static влияет на класс хранения z и не зависит от класса хранения x.)

Если что-то вроде этого было разрешено, static не будет иметь никакого эффекта, поскольку объект не объявляется. Тип с псевдонимом - это просто int.

typedef static int sint;

Ответ 2

Возможно, стандарт должен был назвать эти вещи storage-class-or-typedef-specifier и сказал:

Ограничения: не более одного спецификатора storage-classor-typedef-спецификатора могут быть указаны в спецификаторах декларации в объявлении

Тогда им не пришлось бы добавлять примечание о семантике.

Комментарий о семантике - это просто сказать, что typedef фактически ничего не контролирует память, используемую для этого типа (поэтому он не является семантически "спецификатором хранения" ), но он обрабатывается синтаксически, как другие storage-class-specifier и, следовательно, не могут использоваться с ними.

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

Даже если то, что вы искали, было разрешено, было бы плохой практикой, я уверен. Рассмотрим:

// in someheader.h
typedef static int sint;


// now in foo.c
#include "someheader.h"

int foo(void)
{
    sint i = 10;   // unless you're intimately knowledgeable about how 
                   //    `sint` is typedef'ed, this looks exactly like
                   //    an automatic


    // do some stuff that modifies `i`...

    return i;
}

sint bar(void)    // what does this mean?  is `bar()` static?
{
    return foo();
}

Обратите внимание, что вы используете препроцессор для получения эффекта "статического typedef", который сделает статическую функцию bar(). Который может быть не тем эффектом, который вы хотите. Может быть.

Ответ 3

Вы не можете этого сделать - по крайней мере, не с MinGW GCC - внутри или вне функции.

Вместо этого я использовал бы препроцессор:

#include <stdio.h>

#define sint static int

int main(void)
{

    sint i = 10;

    return 0;
}

Достигает такого же результата.

Я бы это себе представлял, потому что "static int" не является типом таким же образом, как и "volatile int".

Ответ 4

typedef синтаксически совпадает с классом хранения. Это не класс хранения. typedef похож на #define, но typedef интерпретируется Компилятор, а #define - препроцессором. typedef может выполнять текстовые подстановки, выходящие за рамки возможностей препроцессор.

Две цели для использования typedef 1. Портативность 2. Лучшая документация