Является ли 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. Лучшая документация