目录搜索
AlgorithmsAlgorithms(算法)bsearchbsearch_sqsortqsort_sAtomic operationsAtomic operations library(原子操作库)ATOMIC_*_LOCK_FREEatomic_compare_exchange_strongatomic_compare_exchange_strong_explicitatomic_compare_exchange_weakatomic_compare_exchange_weak_explicitatomic_exchangeatomic_exchange_explicitatomic_fetch_addatomic_fetch_add_explicitatomic_fetch_andatomic_fetch_and_explicitatomic_fetch_oratomic_fetch_or_explicitatomic_fetch_subatomic_fetch_sub_explicitatomic_fetch_xoratomic_fetch_xor_explicitatomic_flagatomic_flag_clearatomic_flag_clear_explicitATOMIC_FLAG_INITatomic_flag_test_and_setatomic_flag_test_and_set_explicitatomic_initatomic_is_lock_freeatomic_loadatomic_load_explicitatomic_signal_fenceatomic_storeatomic_store_explicitatomic_thread_fence(线程围栏)ATOMIC_VAR_INITkill_dependencymemory_order(内存排序)C keywordsauto(自动存储)break(跳出循环)C keywords(关键词)casecharconst(常量修饰符)continuedefault(预设运算式)dodouble(双精度浮点型)elseenum(枚举类型)extern(全局变量)float(浮点数)forfortrangoto(goto语句)if(if语句)inline(行内函式)intlong(长整型)register(寄存器变量)restrict( restrict类型限定符)returnshortsignedsizeof(sizeof运算符)static(静态变量)struct(结构体)switch(switch语句)typedef(typedef关键字)union(联合体)unsigned(无符号)void(空类型)volatile(volatile变量)while(while语句)_Alignas_Alignof_Atomic_Bool_Complex_Generic_Imaginary_Noreturn_Static_assert_Thread_localC language#define directive#elif directive#else directive#endif directive#error directive#if directive#ifdef directive#ifndef directive#include directive#line directive#pragma directivealignas(对齐指定符)Alternative operators and tokens(替代运算符和令牌)AnalyzabilityArithmetic operatorsArithmetic typesArray declaration(数组声明)Array initialization(阵列初始化)ASCII ChartAssignment operators(赋值运算符)types(atomic类型限定符)Basic conceptsBit fields(位域)break statementC languageC Operator Precedencecast operatorcharacter constant(字符字面量)Comments(注释符)Comparison operators(比较运算符)compound literals(符合字面量)Conditional inclusion(条件包含)Conformance(一致性)const type qualifier(const 限定符)Constant expressions(常量表达)continue statementDeclarations(声明)do-while loopEnumerations(枚举类型)Escape sequences(转义字符)Expressions(表达式)External and tentative definitions(外部和暂定的定义)File scope(文件范围)floating constant(浮点常量)for loopFunction declarations(函数声明)Function definitions(函数声明)FunctionsGeneric selection泛型选择goto statementIdentifier(标示符)if statementImplicit conversions(隐式转换)Increment/decrement operators(前置/后置操作符)Initialization(初始化)inline function specifier(内联函式)integer constantLifetime(生命期)Logical operators(逻辑运算符)Lookup and name spacesMain function(主函式)Member access operators(会员接入运营商)Memory modelObjects and alignment(字节对齐)Order of evaluation(评估顺序)Other operatorsPhases of translation(翻译阶段)Pointer declarationPreprocessor(预处理)restrict type qualifier(restrict类型限定符)return statementScalar initialization(标量类型初始化)Scope(范围)sizeof operator(sizeof运算符)Statements(陈述)static assert declaration(静态断言声明)Static storage duration(静态存储周期)Storage-class specifiers(存储类说明符)string literals(字符串字面量)Struct and union initialization(结构体与联合体初始化)Struct declaration(结构体声明)switch statementThread storage duration(线程存储时间)TypeType(类型)Typedef declaration(Typedef声明)Undefined behavior(未定义行为)Union declaration(联合体声明)Value categories(值类别)Variadic arguments(变长参数宏)volatile type qualifier(volatile 类型限定符)while loop_Alignof operator_Noreturn function specifierDate and timeasctime(asctime函数)asctime_sclockCLOCKS_PER_SECclock_tctime(ctime函数)ctime_sDate and time utilities(日期和时间库)difftime(计算两个时间的间隔)gmtimegmtime_slocaltimelocaltime_smktime(将时间结构数据转换成经过的秒数的函数)strftime(格式化输出时间函数)timetimespectimespec_gettime_ttmwcsftime(格式化时间宽字符)Dynamic memory managementaligned_allocC memory management library(内存管理库)callocfree(释放动态分配空间的函数)malloc(动态分配内存空间的函数)realloc(重新分配内存空间的函数)Error handlingabort_handler_sassert(断言)constraint_handler_terrno(错误报告)Error handling(错误处理)Error numbers(错误个数)ignore_handler_sset_constraint_handler_sstatic_assertFile input/outputclearerr(清除/复位)fclosefeofferrorfflush(清空文件缓冲区)fgetcfgetposfgetsfgetwcfgetwsFile input/outputfopenfopen_sfprintffprintf_sfputcfputsfputwcfputwsfreadfreopenfreopen_sfscanffscanf_sfseekfsetposftellfwidefwprintffwprintf_sfwritefwscanffwscanf_sgetcgetchargetsgets_sgetwcharperrorprintfprintf_sputcputcharputsputwcputwcharremoverenamerewindscanfscanf_ssetbufsetvbufsnprintfsprintfsscanfsscanf_sswprintfswprintf_sswscanfswscanf_stmpfiletmpfile_stmpnamtmpnam_sungetcungetwcvfprintfvfprintf_svfscanfvfscanf_svfwprintfvfwprintf_svfwscanfvfwscanf_svprintfvprintf_svscanfvscanf_svsnprintfvsprintfvsscanfvsscanf_svswprintfvswprintf_svswscanfvswscanf_svwprintfvwprintf_svwscanfvwscanf_swprintfwprintf_swscanfwscanf_sLocalization supportlconvLC_ALLLC_COLLATELC_CTYPELC_MONETARYLC_NUMERICLC_TIMElocaleconvLocalization supportsetlocaleNumericsabsacosacosfacoshacoshfacoshlacoslasinasinfasinhasinhfasinhlasinlatanatan2atan2fatan2latanfatanhatanhfatanhlatanlcabscabsfcabslcacoscacosfcacoshcacoshfcacoshlcacoslcargcargfcarglcasincasinfcasinhcasinhfcasinhlcasinlcatancatanfcatanhcatanhfcatanhlcatanlcbrtcbrtfcbrtlccosccosfccoshccoshfccoshlccoslceilceilfceillcexpcexpfcexplcimagcimagfcimaglclogclogfcloglCMPLXCMPLXFCMPLXLCommon mathematical functionscomplexComplex number arithmeticconjconjfconjlcopysigncopysignfcopysignlcoscosfcoshcoshfcoshlcoslcpowcpowfcpowlcprojcprojfcprojlcrealcrealfcreallcsincsinfcsinhcsinhfcsinhlcsinlcsqrtcsqrtfcsqrtlctanctanfctanhctanhfctanhlctanldivdouble_terferfcerfcferfclerfferflexpexp2exp2fexp2lexpfexplexpm1expm1fexpm1lfabsfabsffabslfdimfeclearexceptfegetenvfegetexceptflagfegetroundfeholdexceptferaiseexceptfesetenvfesetexceptflagfesetroundfetestexceptfeupdateenvFE_ALL_EXCEPTFE_DFL_ENVFE_DIVBYZEROFE_DOWNWARDFE_INEXACTFE_INVALIDFE_OVERFLOWFE_TONEARESTFE_TOWARDZEROFE_UNDERFLOWFE_UPWARDFloating-point environmentfloat_tfloorfloorffloorlfmafmaffmalfmaxfmaxffmaxlfminfminffminlfmodfmodffmodlfpclassifyFP_INFINITEFP_NANFP_NORMALFP_SUBNORMALFP_ZEROfrexpfrexpffrexplHUGE_VALHUGE_VALFHUGE_VALLhypothypotfhypotlIilogbilogbfilogblimaginaryimaxabsimaxdivINFINITYisfiniteisgreaterisgreaterequalisinfislessislessequalislessgreaterisnanisnormalisunorderedlabsldexpldexpfldexplldivlgammalgammaflgammalllabslldivllrintllrintfllrintlllroundllroundfllroundlloglog10log10flog10llog1plog1pflog1pllog2log2flog2llogblogbflogbllogflogllrintlrintflrintllroundlroundflroundlMATH_ERREXCEPTmath_errhandlingMATH_ERRNOmodfmodffmodflnanNANnanfnanlnearbyintnearbyintfnearbyintlnextafternextafterfnextafterlnexttowardnexttowardfnexttowardlNumericspowpowfpowlPseudo-random number generationrandRAND_MAXremainderremainderfremainderlremquoremquofremquolrintrintfrintlroundroundfroundlscalblnscalblnfscalblnlscalbnscalbnfscalbnlsignbitsinsinfsinhsinhfsinhlsinlsqrtsqrtfsqrtlsrandtantanftanhtanhftanhltanltgammatgammaftgammaltrunctruncftrunclType-generic math_Complex_I_Imaginary_IProgram supportabortatexitat_quick_exitexitEXIT_FAILUREEXIT_SUCCESSgetenvgetenv_sjmp_buflongjmpProgram support utilitiesquick_exitraisesetjmpSIGABRTSIGFPESIGILLSIGINTsignalSIGSEGVSIGTERMsig_atomic_tSIG_DFLSIG_ERRSIG_IGNsystem_ExitStringsatofatoiatolatollbtowcc16rtombc32rtombchar16_tchar32_tisalnumisalphaisblankiscntrlisdigitisgraphislowerisprintispunctisspaceisupperiswalnumiswalphaiswblankiswcntrliswctypeiswdigitiswgraphiswloweriswprintiswpunctiswspaceiswupperiswxdigitisxdigitmblenmbrlenmbrtoc16mbrtoc32mbrtowcmbsinitmbsrtowcsmbsrtowcs_smbstate_tmbstowcsmbstowcs_smbtowcmemchrmemcmpmemcpymemcpy_smemmovememmove_smemsetmemset_sNull-terminated byte stringsNull-terminated multibyte stringsNull-terminated wide stringsstrcatstrcat_sstrchrstrcmpstrcollstrcpystrcpy_sstrcspnstrerrorstrerrorlen_sstrerror_sStrings librarystrlenstrncatThread supportcall_oncecnd_broadcastcnd_destroycnd_initcnd_signalcnd_timedwaitcnd_waitmtx_destroymtx_initmtx_lockmtx_plainmtx_recursivemtx_timedmtx_timedlockmtx_trylockmtx_unlockonce_flagONCE_FLAG_INITthrd_busythrd_createthrd_currentthrd_detachthrd_equalthrd_errorthrd_exitthrd_jointhrd_nomemthrd_sleepthrd_successthrd_timedoutthrd_yieldThread support librarythread_localtss_createtss_deleteTSS_DTOR_ITERATIONStss_gettss_setType supportBoolean type support libraryFixed width integer typesFLT_EVAL_METHODFLT_ROUNDSmax_align_tNULLNumeric limitsoffsetofptrdiff_tsize_tType supportVariadic functionsVariadic functionsva_argva_copyva_endva_listva_start
文字

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

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

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

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

volatile int n = 1; // object of volatile-qualified typeint* 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 intvolatile 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 intint* 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 typeschar * 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来禁用优化。

#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类型限定符

上一篇:下一篇: