C type qualifier

C type qualifier

We usually describe a variable by its type and storage class. C90 also adds two new properties: constancy and volatility. These two properties can be declared using the keywords constand , respectively volatile, and the type created with these two keywords is a qualified type. The C99 standard adds a third qualifier: restrict, to improve compiler optimizations. The C11 standard adds a fourth qualifier: _Atomic. C11 provides an optional library, stdatomic.hmanaged, to support concurrent programming, and _Atomicis optional support.

C99 adds a new attribute to type qualifiers: idempotent, which means that the same qualifier can be used multiple times in a declaration, and redundant qualifiers will be ignored:

const const const int n = 6; // 等同于 const int n = 6;

const type qualifier (C90)

constThe value of an object declared with a keyword cannot be modified by assignment or incrementing and decrementing. In a ANSIcompatible compiler, the following code

const int nochange;  // 限定nochange的值不能被修改
nochange = 12;       // 不允许

The compiler will report an error. But you can initialize constvariables, that is, the following code is no problem

const int nochage = 12; // 编译通过

This declaration makes nochangeit a read-only variable. After initialization, its value cannot be changed.

Using const in pointer and parameter declarations

constQualifiers can be used to modify ordinary variables, arrays and pointers, but when modifying pointers, it is necessary to distinguish whether to qualify the pointer itself constor the value pointed to by the pointer const.

const float *pf; // pf指向一个float类型的const值。 pf指向的值不能被改变,pf本身的值可以改变。
float const *pfc; // 等同于 const float *pfc;
float * const pt; // pt是一个const指针。 pt本身的值不能改变,但其所指向的值可以改变。
const float * const ptr; // 表明ptr本身不能改变,其指向的值也不能改变。

As noted in the comments, putting constafter the type name and before * indicates that the pointer cannot be used to change the value it points to. In short, constplacing it anywhere on the left side of * restricts that the data pointed to by the pointer cannot be changed; constplacing it on the right side of * restricts that the pointer itself cannot be changed.

constA common use of the keyword is to declare a pointer as a function parameter.

void display(const int array[], int limit); // array数组不会被修改。const int array[] 等同于 const int *array

use const for global data

Global variables expose data that can be changed by any part of the program. This danger can be avoided if the data is set to const. So it makes sense to declare global data with constqualifiers, to create constvariables, constdata and conststructures

constThere are two strategies for sharing data between files

Follow the usual rules for external variables

That is, use a definition declaration in one file, and use a reference declaration (with externkeywords) in other files

const variables are placed in all files, and then other files include header files

staticThis scheme must declare global variables with keywords in the header file const. If it is removed static, each file including the header file will have a definitional declaration of the same identifier, that is, each file has a separate copy of the data, because Each copy is only visible to that file, so it cannot use this data to communicate with other files.

The advantage of header files is that it is convenient for you to be lazy and not to worry about using definition declarations in one file and reference declarations in other files. All files need only include the same header file. But its disadvantage is that the data is duplicated. For simple data, this is fine, but if constthe data contains huge arrays, it cannot be ignored.

CWhat are the similarities and differences between Chinese constand C++Chinese const?

To be continued

CNeutralization definedifference const?

  • Compilers handle it differently

    defineMacro definitions are expanded during preprocessing, while constconstants are used during compilation and runtime

  • Type and security checks are different

    defineThe macro definition has no type, does not do any type checking, just replaces the expansion

    constConstants have specific types, and type checking is performed at compile time

  • memory allocation is different

    defineThe macro is only expanded, no memory is allocated

    constConstants are allocated in memory, either the heap or the stack

  • Constants and read-only variables

    Defining constants in C is used enumor definemacros, constants do not need to allocate memory space

    constModified is a read-only variable, not a constant, and cannot be used as an array dimension, nor can it be placed after a casekeyword.

volatile type qualifier (C90)

volatileThe original meaning is volatile, indicating that an agent (not the program in which the variable is located) can change the value of the variable. Usually compilers will read variables from memory into registers in order to optimize and reduce memory read. But if you use the volatiledeclared variable, the system always re-reads the data from memory, that is, no optimization is performed. If not applicable volatile, the compiler may declare the statement for optimization. Simply put, the volatilekeyword affects the compiler's compilation results. volatileThe declared variable indicates that the variable may change at any time. Do not optimize related operations to avoid errors.

Suppose you have the following code

val1 = x;
/* 一些不适应x的代码 */
val2 = x;

A smart (optimizing) compiler will notice that the above code is used twice x, but not change its value. The compiler then xtemporarily stores the value in a register, and then val2uses the value xread from the register (instead of the original memory location) xto save time. This process is called caching. In general, caching is a good optimization, but if some other proxy changes the xvalue between the two statements above, it can't be optimized this way. Without volatilethe keyword, the compiler will try to optimize the code by assuming that the value of the variable does not change during use.

Can have constand volatilequalify a value at the same time. For example, it is usually used constto set the hardware clock to a variable that cannot be changed by the program, but can be changed by a proxy 1volatile. Both qualifiers can only be used together in a declaration, the order does not matter

volatile const int loc;
const volatile int * ploc;

restrict type qualifier (C99)

restrictKeywords allow the compiler to optimize certain parts of the code to better support computation. It can only be used for pointers, indicating that the pointer is the only and initial way to access the data object. Suppose the following code

int ar[10];
int * restrict restar = (int *) malloc (10 * sizeof(int));
int *par = ar;

Here, pointers are the only and initial way restarto access the memory allocated by . malloc()Therefore, it can be restrictqualified with keywords. And pointers parare neither arthe initial nor the only way to access data in an array. So don't set it torestrict

Now consider the following slightly more complex example, where nthe inttype

for(n = 0; n < 10; n++)
{
    par[n] += 5;
    restar[n] = 5;
    ar[n] *= 2;
    par[n] += 3;
    restar[n] += 3;
}

Since life before restaris the only and initial way to access the data block it points to, the compiler can restarreplace the two statements involved with the following, with the same effect:

restar[n] += 8; /* 可以进行替换 */

However, parreplacing the two related statements with the following will result in a calculation error:

par[n] += 8;  /* 给出错误的结果 */

This is because the forloop changes the value of that pardata between two accesses to the same data .ar

In this example, if the restrictkeyword is not used, the compiler must assume the worst case (ie, other identifiers may have changed data between uses of the pointer). If the restrictkeyword is used, the compiler can choose a shortcut to optimize the computation.

restrictQualifiers can also be used on pointers to function parameters. This means that the compiler can assume that other identifiers in the function body will not modify the data pointed to by the pointer, and the compiler can try to optimize it for no other use. For example, the C library has two functions for copying bytes from one location to another. In C99, the prototypes of these two functions are

void * memcpy(void * restrict s1, const void * restrict s2, size_t n);
void * memmove(void * s1, const void * s2, size_t n);

Both functions copy bytes from position to s2position . The function requires that the two positions do not overlap, but there is no such requirement. Declaring and stating that these two pointers are the only way to access the corresponding data, so they cannot access the same block of data. This satisfies the requirement that the functions do not overlap. Overlap is allowed, it has to be more careful when copying the data to prevent overwriting the data before using it.ns1memcpy()memove()s1s2restrictmemcpy()memmove()

restrictKeywords have two readers. One is the compiler, this keyword tells the compiler that it is free to assume some optimization scheme. Another reader is the user, and this keyword tells the user to use restrictparameters that satisfy the requirements. In summary, the compiler does not check that the user follows this restriction, but ignores it at your own risk.

_Atomic type qualifier (C11)

Concurrent programming divides program execution into multiple threads that can execute simultaneously. This programming introduces new challenges, including how to manage different threads accessing the same data. C11 provides some optional (not mandatory) management methods by including optional header files stdatomic.hand . threads.hIt is worth noting that the yard type is accessed through various macro functions. When a thread performs an atomic operation on an object of atomic type, other threads cannot access the formation. For example, the following code:

int hogs; // 普通声明
hogs = 12; // 普通赋值
// 替换为
_Atomic int hogs; // hogs是一个原子类型的变量
atomic_store(&hogs, 12); // stdatomic.h 中的宏

Here, hogsstoring 12in is an atomic process and cannot be accessed by other threads hogs.

The premise of writing this kind of code is that the compiler supports this new feature.

refer to

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325629401&siteId=291194637