2011-12-29 7 views
15

Próbowałem następujący kodCzy typedef jest specyfikatorem klasy pamięci?

#include <stdio.h> 

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

    return 0; 
} 

i hit następujący błąd:

error: multiple storage classes in declaration specifiers 

Kiedy przekazał specyfikację C99, poznałem, że typedef jest 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; 

Jedynym wyjaśnieniem, że udało mi się znaleźć (w oparciu o niektóre przeszukiwanie internetu i krzyż odnosząc różne sekcje w specyfikacji C99) był syntactic convenience only to make the grammar simpler.

Szukam uzasadnienia/wyjaśnienia, w jaki sposób nazwa typu może mieć specyfikator klasy pamięci?

Czy nie ma sensu posiadanie kodu takiego jak typedef static int sint;?

lub Gdzie się mylę ?!

Odpowiedz

14

Tak, typedef jest specyfikatorem klasy pamięci, jaki został znaleziony w standardzie. Częściowo jest to gramatyczna wygoda, ale celowe jest, że możesz albo mieć jeden z bardziej "oczywistych" specyfikatorów klasy pamięci, albo typedeflub.

Deklaracja typedef tworzy alias dla typu.

W deklaracji static int x; typ x to int. static nie ma nic wspólnego z typem.

(Weź pod uwagę adres x, &x ma typ int*.int *y = &x; byłoby legalne tak jak static int *z = &x ale ten ostatni static wpływa na klasę przechowywania z i jest niezależna od klasy przechowywania x.)

Jeśli coś takiego mogli się static miałoby żadnego wpływu, jak żaden obiekt jest zadeklarowana . Typ aliasowany to tylko int.

typedef static int sint; 
+1

patrz: http://stackoverflow.com/questions/2218435/why-typedef-can-not-be-used-with-static – Demi

4

Może norma powinna nazwali te rzeczy storage-class-or-typedef-specifier i powiedział:

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

wtedy nie musiałby dodaje notatkę o semantyce.

Komentarz na temat semantyki mówi po prostu, że typedef faktycznie nie kontroluje niczego na temat pamięci używanej dla danego typu (dlatego nie jest semantycznie "specyfikatorem pamięci"), ale jest traktowane syntaktycznie jak inne storage-class-specifier i dlatego nie można z nimi korzystać.

Tak więc nie może ustalić, gdzie będzie przechowywane konkretne wystąpienie typu - jest to określone przez faktyczną deklarację instancji (domyślnie lub jawnie).

Nawet jeśli to, czego szukasz, jest dozwolone, to na pewno byłaby to zła praktyka. Rozważmy:

// 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(); 
} 

Zauważ, że jest użyć preprocesor aby uzyskać efekt „static typedef”, która stałaby bar() funkcją statycznego. Który może nie być efektem, który chcesz. Może.

1

Nie można tego zrobić - przynajmniej nie w GCC MinGW - zarówno wewnątrz, jak i na zewnątrz funkcji.

użyję preprocesor zamiast:

#include <stdio.h> 

#define sint static int 

int main(void) 
{ 

    sint i = 10; 

    return 0; 
} 

osiąga ten sam wynik.

Wyobrażam sobie, że to dlatego, że "static int" nie jest typem w taki sam sposób jak "volatile int".

+0

Sh00t, masz rację. Myliłem to z 'signed'. –

+3

Nie rób tego. Po prostu sprawi, że kod będzie bardziej zagmatwany, niż musi być, 'sint' nie będzie użyteczny jako typ parametru, a funkcja zwracająca' sint' będzie miała właściwość, która prawdopodobnie nie jest zamierzona (wewnętrzne powiązanie). –

-1

Typedef jest syntaktycznie taki sam jak klasa przechowywania. To nie jest klasa pamięci. typedef jest podobny do #define, ale typedef jest interpretowany przez kompilator podczas gdy #define jest przez preprocesor. Typedef może dokonywać podstawień tekstowych, które są poza możliwościami preprocesora.

dwóch celach korzystania typedef 1. Przenośność 2. Lepsza dokumentacja

Powiązane problemy