Kwalifikatory typów

Kwalifikatory typu dają jedną z dwóch właściwości identyfikatorowi. Kwalifikator const typu deklaruje obiekt, który ma być niemodyfikowalny. Kwalifikator volatile typu deklaruje element, którego wartość może zostać wiarygodnie zmieniona przez coś poza kontrolą programu, w którym się pojawia, na przykład współbieżnie wykonujący wątek.

Kwalifikatory typu , constrestricti volatile, mogą być wyświetlane tylko raz w deklaracji. Kwalifikatory typów mogą być wyświetlane z dowolnym specyfikatorem typu; nie mogą jednak pojawiać się po pierwszym przecince w deklaracji wielokrotnego elementu. Na przykład następujące deklaracje są legalne:

typedef volatile int VI;
const int ci;

Te deklaracje nie są legalne:

typedef int *i, volatile *vi;
float f, const cf;

Kwalifikatory typów są istotne tylko w przypadku uzyskiwania dostępu do identyfikatorów jako wartości l w wyrażeniach. Zobacz Wyrażenia L-Value i R-Value, aby uzyskać informacje o wartościach l i wyrażeniach.

Składnia

type-qualifier:
const
restrict
volatile

const i volatile

Poniżej przedstawiono oświadczenia prawne i volatile prawneconst:

int const *p_ci;      // Pointer to constant int
int const (*p_ci);   // Pointer to constant int
int *const cp_i;     // Constant pointer to int
int (*const cp_i);   // Constant pointer to int
int volatile vint;     // Volatile integer

Jeśli specyfikacja typu tablicy zawiera kwalifikatory typu, element jest kwalifikowany, a nie typ tablicy. Jeśli specyfikacja typu funkcji zawiera kwalifikatory, zachowanie jest niezdefiniowane. volatile i const nie wpływają na zakres wartości ani właściwości arytmetycznych obiektu.

  • Słowo const kluczowe może służyć do modyfikowania dowolnego typu podstawowego lub agregowanego albo wskaźnika do obiektu dowolnego typu lub .typedef Jeśli element jest zadeklarowany tylko z kwalifikatorem const typu, jego typ jest przyjmowany jako const int. Zmienną const można zainicjować lub umieścić w regionie magazynu tylko do odczytu. Słowo const kluczowe jest przydatne do deklarowania wskaźników, const ponieważ wymaga to, aby funkcja nie zmieniała wskaźnika w żaden sposób.

  • Kompilator zakłada, że w dowolnym momencie programu volatile można uzyskać dostęp do zmiennej przez nieznany proces, który używa lub modyfikuje jego wartość. Niezależnie od optymalizacji określonych w wierszu polecenia, kod dla każdego przypisania do lub odwołania do zmiennej volatile musi zostać wygenerowany, nawet jeśli wydaje się, że nie ma żadnego wpływu.

Jeśli volatile jest używany sam, zakłada się, int że. Specyfikator volatile typu może służyć do zapewnienia niezawodnego dostępu do specjalnych lokalizacji pamięci. Używanie volatile z obiektami danych, które mogą być dostępne lub zmieniane przez programy obsługi sygnałów, współbieżnie wykonując programy lub przez specjalny sprzęt, taki jak zamapowane na pamięć rejestry we/wy. Możesz zadeklarować zmienną jako volatile okres istnienia lub rzutować pojedyncze odwołanie na wartość volatile.

  • Element może być zarówno const elementem, jak i volatile, w którym przypadku element nie może być legalnie zmodyfikowany przez własny program, ale może zostać zmodyfikowany przez jakiś proces asynchroniczny.

restrict

Kwalifikator restrict typu wprowadzony w języku C99 i dostępny w /std:c11 trybie lub /std:c17 może być stosowany do deklaracji wskaźników. Kwalifikuje wskaźnik, a nie to, co wskazuje.

restrict jest wskazówką optymalizacji kompilatora, że żaden inny wskaźnik w bieżącym zakresie nie odnosi się do tej samej lokalizacji pamięci. Oznacza to, że tylko wskaźnik lub wartość uzyskana z niego (na przykład wskaźnik + 1) jest używana do uzyskiwania dostępu do obiektu w okresie istnienia wskaźnika. Pomaga to kompilatorowi wygenerować bardziej zoptymalizowany kod. Język C++ ma równoważny mechanizm, __restrict

Należy pamiętać, że restrict jest to kontrakt między Tobą a kompilatorem. Jeśli utworzysz alias wskaźnika oznaczonego symbolem restrict, wynik jest niezdefiniowany.

Oto przykład, który używa elementu restrict:

void test(int* restrict first, int* restrict second, int* val)
{
    *first += *val;
    *second += *val;
}

int main()
{
    int i = 1, j = 2, k = 3;
    test(&i, &j, &k);

    return 0;
}

// Marking union members restrict tells the compiler that
// only z.x or z.y will be accessed in any scope, which allows
// the compiler to optimize access to the members.
union z 
{
    int* restrict x;
    double* restrict y;
};

Zobacz też

/std (Określ wersję standardową języka)
Deklaracje i typy