目录搜索
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中的一个,两个或全部三个,并且对于指向对象类型的指针,限制限定符。本页介绍的影响限制预选赛。

仅指向对象类型可以是限制合格(特别地,int restrict *pfloat (* restrict f9)(void)是错误)。

限制语义仅适用于左值表达式; 例如,转换为限制限定指针或返回限制限定指针的函数调用不是左值,并且限定符不起作用。

P声明限制指针的块的每次执行过程中(通常每个函数体的每个执行P都是一个函数参数),如果通过P(直接或间接)方式访问的某个对象以任何方式被修改,则所有在该块中访问该对象(读取和写入)必须通过P(直接或间接)发生,否则行为未定义:

void f(int n, int * restrict p, int * restrict q){    while(n-- > 0)        *p++ = *q++; // none of the objects modified through *p is the same                     // as any of the objects read through *q                     // compiler free to optimize, vectorize, page map, etc.}void g(void){
    extern int d[100];    f(50, d + 50, d); // OK    f(50, d + 1, d); // Undefined behavior: d[1] is accessed through both p and q in f}

如果对象从不修改,则可能会被别名和通过不同的限制限定指针访问(请注意,如果由别名限制限定指针指向的对象又是指针,则此别名可能会禁止优化)。

从一个受限指针指向另一个受限指针是未定义的行为,除非将指向某个外部块中的对象的指针指定给某个内部块中的指针(包括在调用具有受限指针参数的函数时使用受限指针参数),或者何时从一个函数返回(否则当from-pointer结束时):

int* restrict p1 = &a;int* restrict p2 = &b;p1 = p2; // undefined behavior

受限制的指针可以自由分配给无限制的指针,只要编译器能够分析代码,优化机会就会保持原状:

void f(int n, float * restrict r, float * restrict s) {
   float * p = r, * q = s; // OK   while(n-- > 0) *p++ = *q++; // almost certainly optimized just like *r++ = *s++}

如果使用限制类型限定符(通过使用typedef)声明数组类型,则数组类型不受限制,但其元素类型为:

typedef int *array_t[10];restrict array_t a; // the type of a is int *restrict[10]

在函数声明中,关键字restrict可能出现在用于声明函数参数的数组类型的方括号内。它限定了数组类型转换的指针类型:

void f(int m, int n, float a[restrict m][n], float b[restrict m][n]);void g12(int n, float (*p)[n]) {   f(10, n, p, p+10); // OK   f(20, n, p, p+10); // possibly undefined behavior (depending on what f does)}

注意

限制限定符(如注册存储类)的预期用途是促进优化,并且从组成合格程序的所有预处理翻译单元中删除所有限定符的实例不会改变其含义(即可观察到的行为)。

编译器可以自由地忽略使用的任何或所有别名含义restrict

为了避免未定义的行为,程序员必须确保不受违反限制限制指针的别名声明。

作为语言扩展,许多编译器提供了与之相反restrict的属性:一个属性,指示即使类型不同,指针也可以是别名:may_alias(gcc),

限制限定指针有几种常见的使用模式:

文件范围

文件范围限制限定指针必须在程序期间指向单个数组对象。该数组对象不能通过受限制的指针和声明的名称(如果它有一个)或另一个受限制的指针来引用。

文件范围受限指针在提供对动态分配的全局数组的访问时很有用; 限制语义可以通过这个指针来优化引用,就像通过声明名称引用静态数组一样有效:

float * restrict a, * restrict b;float c[100];
 int init(int n) {
   float * t = malloc(2*n*sizeof(float));
   a = t;      // a refers to 1st half
   b = t + n;  // b refers to 2nd half}// compiler can deduce from the restrict qualifiers that// there is no potential aliasing among the names a, b, and c

函数参数

限制限定指针最常用的用例是用作函数参数。

在以下示例中,编译器可能会推断出没有修改对象的别名,因此积极优化循环。一旦进入f,受限指针a必须提供对其相关阵列的独占访问权限。特别是,在f中,b和c都不会指向与a相关的数组,因为它们都不会被指定基于a的指针值。对于b,从声明中的const限定词中可以明显看出,但对于c,需要检查f的主体:

float x[100];float *c;void f(int n, float * restrict a, float * const b) {
    int i;    for ( i=0; i<n; i++ )
       a[i] = b[i] + c[i];}void g3(void) {
    float d[100], e[100];
    c = x; f(100,   d,    e); // OK           f( 50,   d, d+50); // OK           f( 99, d+1,    d); // undefined behavior
    c = d; f( 99, d+1,    e); // undefined behavior           f( 99,   e,  d+1); // OK}

请注意,允许c指向与b关联的数组。还要注意,出于这些目的,与特定指针关联的“数组”只意味着通过该指针实际引用的数组对象的那部分。

块范围

块范围限制限定指针使得限制为其块的别名断言成为可能。它允许局部断言只适用于重要的块,比如紧密的循环。它还可以将一个将限制合格指针的函数转换为一个宏:

float x[100];float *c;#define f3(N, A, B)                                    \{   int n = (N);                                       \
    float * restrict a = (A);                          \
    float * const    b = (B);                          \
    int i;                                             \    for ( i=0; i<n; i++ )                              \
        a[i] = b[i] + c[i];                            \}

结构成员

由作为结构成员的限制限定指针产生的别名声明的范围是用于访问该结构的标识符的范围。

即使结构在文件范围内声明,当用于访问结构的标识符具有块范围时,结构中的别名声明也具有块范围; 别名声明仅在块执行或函数调用中生效,具体取决于如何创建此结构类型的对象:

struct t {    // Restricted pointers assert that   
   int n;     // members point to disjoint storage.
   float * restrict p;
   float * restrict q;}; void ff(struct t r, struct t s) {
   struct t u;   // r,s,u have block scope   // r.p, r.q, s.p, s.q, u.p, u.q should all point to   // disjoint storage during each execution of f.   // ...}

关键词

restrict.

代码生成示例; 用-S(gcc,clang等)或/ FA(visual studio)编译。

int foo(int *a, int *b){    *a = 5;    *b = 6;    return *a + *b;}
 int rfoo(int *restrict a, int *restrict b){    *a = 5;    *b = 6;    return *a + *b;}

可能的输出:

# generated code on 64bit Intel platform:foo:
    movl    $5, (%rdi)    # store 5 in *a
    movl    $6, (%rsi)    # store 6 in *b    movl    (%rdi), %eax  # read back from *a in case previous store modified it
    addl    $6, %eax      # add 6 to the value read from *a
    ret
 
rfoo:
    movl      $11, %eax   # the result is 11, a compile-time constant
    movl      $5, (%rdi)  # store 5 in *a
    movl      $6, (%rsi)  # store 6 in *b
    ret
上一篇:下一篇: