非常教程

C参考手册

C 语法

volatile type qualifier

C类型系统中的每个单独类型都具有该类型的多个限定版本,对应于const,volatile中的一个,两个或全部三个,并且对于指向对象类型的指针,限制限定符。该页面描述了volatile限定符的影响。

通过volatile限定类型的左值表达式进行的每次访问(包括读取和写入)都被认为是可观察的副作用,并且严格按照抽象机器的规则进行评估(即,所有写入均在在下一个序列点之前的某个时间)。这意味着在单个执行线程中,相对于由易失性访问序列点分隔的另一个可见副作用,无法优化或重新排序易失性访问。

将非易失性值转换为易失性类型不起作用。要使用易失性语义访问非易失性对象,必须将其地址强制转换为易失性指针,然后必须通过该指针进行访问。

任何尝试读取或写入类型为volatile的对象 - 通过非易失性左值限定会导致未定义的行为:

volatile int n = 1; // object of volatile-qualified type
int* p = (int*)&n;
int val = *p; // undefined behavior

一个挥发性限定结构或联合类型的成员获取它所属类型的限定条件(在使用.操作员或->操作员进行访问时):

struct s { int i; const int ci; } s;
// the type of s.i is int, the type of s.ci is const int
volatile struct s vs;
// the types of vs.i and vs.ci are volatile int and const volatile int

如果使用volatile类型限定符(通过使用typedef)声明数组类型,则数组类型不是volatile限定的,但其元素类型为。如果一个函数类型被声明为具有限定的volatile类型(通过使用typedef),则行为是未定义的。

typedef int A[2][3];
volatile A a = {{4, 5, 6}, {7, 8, 9}}; // array of array of volatile int
int* pi = a[0]; // Error: a[0] has type volatile int*

在函数声明中,关键字volatile可能出现在用于声明函数参数数组类型的方括号内。它限定了数组类型被转换的指针类型。以下两个声明声明了相同的函数:void f(double xvolatile,const double yvolatile); void f(double * volatile x,const double * volatile y);

(自C99以来)

指向非易失性类型的指针可以隐式转换为指向相同或兼容类型的volatile限定版本的指针。逆转换可以使用强制表达式来执行。

int* p = 0;
volatile int* vp = p; // OK: adds qualifiers (int to volatile int)
p = vp; // Error: discards qualifiers (volatile int to int)
p = (int*)vp; // OK: cast

请注意,指向指针的指针T不能转换为指向指针的指针volatile T; 对于两种类型的兼容,其资格必须相同:

char *p = 0;
volatile char **vpp = &p; // Error: char* and volatile char* are not compatible types
char * volatile *pvp = &p; // OK, adds qualifiers (char* to char*volatile)

易变的用途

1)静态volatile对象模型存储器映射的I / O端口和static const volatile对象模型存储器映射的输入端口,例如实时时钟:

volatile short *ttyport = (volatile short*)TTYPORT_ADDR;
for(int i = 0; i < N; ++i)
    *ttyport = a[i]; // *ttyport is an lvalue of type volatile short

2)static volatile类型的对象sig_atomic_t用于与signal处理程序进行通信。

3)volatile包含setjmp宏调用的函数的局部变量是保证在longjmp返回后保留其值的唯一局部变量。

4)此外,可以使用volatile变量来禁用某些形式的优化,例如,禁用dead store消除或对microbenchmarks进行常量折叠。

请注意,volatile变量不适合线程之间的通信; 他们不提供原子性,同步或内存排序。从另一个线程修改的易失性变量中读取来自两个未同步的线程的同步或并发修改是由于数据竞争造成的未定义行为。

关键词

volatile.

演示了如何使用volatile来禁用优化。

#include <stdio.h>
#include <time.h>
 
int main(void)
{
    clock_t t = clock();
    double d;
    for (int n=0; n<10000; ++n)
       for (int m=0; m<10000; ++m)
           d += d*n*m; // reads and writes to a non-volatile 
    printf("Modified a non-volatile variable 100m times. "
           "Time used: %.2f seconds\n",
           (double)(clock() - t)/CLOCKS_PER_SEC);
 
    t = clock();
    volatile double vd;
    for (int n=0; n<10000; ++n)
       for (int m=0; m<10000; ++m)
           vd += vd*n*m; // reads and writes to a volatile 
    printf("Modified a volatile variable 100m times. "
           "Time used: %.2f seconds\n",
           (double)(clock() - t)/CLOCKS_PER_SEC);
}

可能的输出:

Modified a non-volatile variable 100m times. Time used: 0.00 seconds
Modified a volatile variable 100m times. Time used: 0.79 seconds

参考

  • C11标准(ISO / IEC 9899:2011):
    • 6.7.3类型限定符(p:121-123)
  • C99标准(ISO / IEC 9899:1999):
    • 6.7.3类型限定符(p:108-110)
  • C89 / C90标准(ISO / IEC 9899:1990):
    • 3.5.3类型限定符

C 语法相关

1.#define directive
2.#elif directive
3.#else directive
4.#endif directive
5.#error directive
6.#if directive
7.#ifdef directive
8.#ifndef directive
9.#include directive
10.#line directive
11.#pragma directive
12.alignas
13.Alternative operators and tokens
14.Analyzability
15.Arithmetic operators
16.Arithmetic types
17.Array declaration
18.Array initialization
19.ASCII Chart
20.Assignment operators
21. types
22.Basic concepts
23.Bit fields
24.break statement
25.C language
26.C Operator Precedence
27.cast operator
28.character constant
29.Comments
30.Comparison operators
31.compound literals
32.Conditional inclusion
33.Conformance
34.const type qualifier
35.Constant expressions
36.continue statement
37.Declarations
38.do-while loop
39.Enumerations
40.Escape sequences
41.Expressions
42.External and tentative definitions
43.File scope
44.floating constant
45.for loop
46.Function declarations
47.Function definitions
48.Functions
49.Generic selection
50.goto statement
51.Identifier
52.if statement
53.Implicit conversions
54.Increment/decrement operators
55.Initialization
56.inline function specifier
57.integer constant
58.Lifetime
59.Logical operators
60.Lookup and name spaces
61.Main function
62.Member access operators
63.Memory model
64.Objects and alignment
65.Order of evaluation
66.Other operators
67.Phases of translation
68.Pointer declaration
69.Preprocessor
70.restrict type qualifier
71.return statement
72.Scalar initialization
73.Scope
74.sizeof operator
75.Statements
76.static assert declaration
77.Static storage duration
78.Storage-class specifiers
79.string literals
80.Struct and union initialization
81.Struct declaration
82.switch statement
83.Thread storage duration
84.Type
85.Type
86.Typedef declaration
87.Undefined behavior
88.Union declaration
89.Value categories
90.Variadic arguments
91.while loop
92._Alignof operator
93._Noreturn function specifier
C

C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。