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 const
and , 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.h
managed, to support concurrent programming, and _Atomic
is 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)
const
The value of an object declared with a keyword cannot be modified by assignment or incrementing and decrementing. In a ANSI
compatible compiler, the following code
const int nochange; // 限定nochange的值不能被修改
nochange = 12; // 不允许
The compiler will report an error. But you can initialize const
variables, that is, the following code is no problem
const int nochage = 12; // 编译通过
This declaration makes nochange
it a read-only variable. After initialization, its value cannot be changed.
Using const in pointer and parameter declarations
const
Qualifiers 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 const
or 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 const
after the type name and before * indicates that the pointer cannot be used to change the value it points to. In short, const
placing it anywhere on the left side of * restricts that the data pointed to by the pointer cannot be changed; const
placing it on the right side of * restricts that the pointer itself cannot be changed.
const
A 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 const
qualifiers, to create const
variables, const
data and const
structures
const
There 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 extern
keywords) in other files
const variables are placed in all files, and then other files include header files
static
This 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 const
the data contains huge arrays, it cannot be ignored.
C
What are the similarities and differences between Chinese const
and C++
Chinese const
?
To be continued
C
Neutralization define
difference const
?
Compilers handle it differently
define
Macro definitions are expanded during preprocessing, whileconst
constants are used during compilation and runtimeType and security checks are different
define
The macro definition has no type, does not do any type checking, just replaces the expansionconst
Constants have specific types, and type checking is performed at compile timememory allocation is different
define
The macro is only expanded, no memory is allocatedconst
Constants are allocated in memory, either the heap or the stackConstants and read-only variables
Defining constants in C is used
enum
ordefine
macros, constants do not need to allocate memory spaceconst
Modified is a read-only variable, not a constant, and cannot be used as an array dimension, nor can it be placed after acase
keyword.
volatile type qualifier (C90)
volatile
The 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 volatile
declared 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 volatile
keyword affects the compiler's compilation results. volatile
The 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 x
temporarily stores the value in a register, and then val2
uses the value x
read from the register (instead of the original memory location) x
to save time. This process is called caching. In general, caching is a good optimization, but if some other proxy changes the x
value between the two statements above, it can't be optimized this way. Without volatile
the keyword, the compiler will try to optimize the code by assuming that the value of the variable does not change during use.
Can have const
and volatile
qualify a value at the same time. For example, it is usually used const
to 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)
restrict
Keywords 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 restar
to access the memory allocated by . malloc()
Therefore, it can be restrict
qualified with keywords. And pointers par
are neither ar
the 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 n
the int
type
for(n = 0; n < 10; n++)
{
par[n] += 5;
restar[n] = 5;
ar[n] *= 2;
par[n] += 3;
restar[n] += 3;
}
Since life before restar
is the only and initial way to access the data block it points to, the compiler can restar
replace the two statements involved with the following, with the same effect:
restar[n] += 8; /* 可以进行替换 */
However, par
replacing the two related statements with the following will result in a calculation error:
par[n] += 8; /* 给出错误的结果 */
This is because the for
loop changes the value of that par
data between two accesses to the same data .ar
In this example, if the restrict
keyword is not used, the compiler must assume the worst case (ie, other identifiers may have changed data between uses of the pointer). If the restrict
keyword is used, the compiler can choose a shortcut to optimize the computation.
restrict
Qualifiers 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 s2
position . 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.n
s1
memcpy()
memove()
s1
s2
restrict
memcpy()
memmove()
restrict
Keywords 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 restrict
parameters 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.h
and . threads.h
It 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, hogs
storing 12
in 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
- C Primer Plus (Sixth Edition) Chinese Version
- restrict keyword in C99