Udostępnij za pośrednictwem


Kwalifikatory typów

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

Kwalifikatory typów, const, restricti volatile, mogą być wyświetlane tylko raz w deklaracji. Kwalifikatory typów mogą być wyświetlane z dowolnym specyfikatorem typu; nie mogą jednak pojawić się po pierwszym przecinku w deklaracji wielu elementów. 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 deklaracje 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 mają wpływu 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 pobierany 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 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, int przyjmuje się, ż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, przez współbieżne wykonywanie programów lub przez specjalny sprzęt, taki jak rejestry kontroli we/wy mapowane w pamięci. Zmienną można zadeklarować jako volatile okres istnienia lub można rzutować pojedyncze odwołanie na volatile.

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

restrict

restrict Kwalifikator 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, na co wskazuje.

restrict to wskazówka optymalizacji dla 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ść pochodząca z niego (na przykład wskaźnik + 1) jest używana do uzyskiwania dostępu do obiektu w okresie istnienia wskaźnika. Ułatwia to kompilatorowi tworzenie bardziej zoptymalizowanego kodu. Język C++ ma równoważny mechanizm, __restrict

Należy pamiętać, że restrict jest to kontrakt między Użytkownikiem 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