目录搜索
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
文字

当预期在不同类型的值的上下文中使用表达式时,可能会发生转换

int n = 1L; // expression 1L has type long, int is expectedn = 2.1; // expression 2.1 has type double, int is expectedchar *p = malloc(10); // expression malloc(10) has type void*, char* is expected

转换发生在以下情况:

按照分配进行转换

  • 在赋值运算符中,右侧操作数的值被转换为左侧操作数的非限定类型。

  • 在标量初始化中,初始化表达式的值被转换为被初始化的对象的非限定类型

  • 在函数调用表达式中,对于具有原型的函数,将每个参数表达式的值转换为相应参数的非限定声明类型

  • 在return语句中,操作数的值return被转换为具有函数返回类型的对象

请注意,除转换外,实际分配也会从浮点类型中移除额外的范围和精度,并禁止重叠; 这些特性不适用于转换,就像通过分配一样。

默认参数优化

在调用时的函数调用表达式中。

1)没有原型的功能

2)可变参数函数,其中参数表达式是与省略号参数匹配的尾随参数之一

整数类型的每个参数都经过整数提升(参见下文),并且每个类型的参数都float被隐式转换为类型double

int add_nums(int count, ...);int sum = add_nums(2, 'c', true); // add_nums is called with three ints: (2, 99, 1)

请注意,float complexfloat imaginary没有提升到double complexdouble imaginary在这种情况下。

通常的算术转换

以下算术运算符的参数经过隐式转换,以获得公共实数类型,这是执行计算的类型:

  • 二进制算术*,/,%,+, -

  • 关系运算符<,>,<=,> =,==,!=

  • 二进制按位运算&,^,|,

  • 条件操作符?:

1)如果一个操作数是long doublelong double complexlong double imaginary,另一个操作数被隐式转换如下:

  • 整数或实际浮动类型 long double

  • 复杂类型 long double complex

  • 虚构类型 long double imaginary

2)否则,如果一个操作数是doubledouble complexdouble imaginary,另一个操作数被隐式转换如下:

  • 整数或实际浮动类型 double

  • 复杂类型 double complex

  • 虚构类型 double imaginary

3)否则,如果一个操作数是floatfloat complexfloat imaginary,另一个操作数被隐式转换如下:

  • 整数类型为float(唯一可能的实际类型是float,保持原样)

  • 复杂类型依然存在 float complex

  • 虚构类型仍然存在 float imaginary

4)否则,两个操作数都是整数。在这种情况下,首先,两个操作数都进行整数升级(见下文)。然后

  • 如果促销后的类型相同,则该类型是常见类型

  • 否则,如果促销后的两个操作数具有相同的签名(均为有符号或无符号),则具有较低转换等级的操作数(请参见下文)会隐式转换为具有较高转换等级的操作数的类型

  • 否则,签名会有所不同:如果具有无符号类型的操作数的转换等级大于或等于有符号操作数类型的等级,则带符号类型的操作数将隐式转换为无符号类型

  • 否则,签名是不同的,并且带符号的操作数的等级大于无符号的操作数的等级。在这种情况下,如果有符号类型可以表示所有无符号类型的值,那么具有无符号类型的操作数将隐式转换为有符号操作数的类型。

  • 否则,两个操作数都会隐式转换为带符号操作数类型的无符号类型。

1.f + 20000001; // int is converted to float, giving 20000000.00                // addition and then rounding to float gives 20000000.00(char)'a' + 1L; // First, char is promoted back to int.                // this is signed + signed case, different rank                // int is converted to long, the result is 98 signed long2u - 10; // signed / unsigned, same rank         // 10 is converted to unsigned, unsigned math is modulo UINT_MAX+1         // assuming 32 bit ints, result is 4294967288 of type unsigned int (aka UINT_MAX-7)0UL - 1LL; // signed/unsigned diff rank, rank of signed is greater.           // If sizeof(long) == sizeof(long long), signed cannot represent all unsigned           // this is the last case: both operands are converted to unsigned long long           // the result is 18446744073709551615 (ULLONG_MAX) of type unsigned long long

结果类型确定如下:

  • 如果两个操作数都很复杂,则结果类型很复杂

  • 如果两个操作数都是虚构的,则结果类型是虚构的

  • 如果两个操作数都是实数,则结果类型是实数

  • 如果两个浮点操作数具有不同的类型域(复数与实数,复数与虚数,或虚数与实数),则结果类型很复杂

double complex z = 1 + 2*I;double f = 3.0;z + f; // z remains as-is, f is converted to double, the result is double complex

与往常一样,浮点运算符的结果可能比其类型所指示的范围和精度更高(请参阅参考资料FLT_EVAL_METHOD)。

注意:实数和虚数操作数不会隐式转换为复数,因为这样做需要额外的计算,而在涉及无穷大,NaN和带符号的零的某些情况下会产生不希望的结果。例如,如果将实数转换为复数,则2.0×(3.0 +i∞)将评估为(2.0 + i0.0)×(3.0 +i∞)⇒(2.0×3.0-0.0×∞)+ i(2.0× ∞+ 0.0×3.0)⇒NaN +i∞而不是正确的6.0 +i∞。如果虚数转换为复数,则i2.0×(∞+ i3.0)将评估为(0.0 + i2.0)×(∞+ i3.0)⇒(0.0×∞ -  2.0×3.0)+ i(0.0 ×3.0 + 2.0×∞)⇒NaN +i∞而不是-6.0 +i∞。

注意:无论通常的算术转换如何,在as-if规则下,通过这些规则,计算总是可以以窄于指定符的类型执行。

价值转化

左值转换

任何非数组类型的任何左值表达式,当在除。以外的任何上下文中使用时。

  • 作为操作符的操作数(如果允许)

  • 作为前/后增量和减量运算符的操作数。

  • 作为成员访问(点)运算符的左侧操作数。

  • 作为赋值和复合赋值操作符的左侧操作数。

  • 作为 sizeof 的操作数

进行左值转换:类型保持不变,但会丢失 const / volatile / restrict-qualifiers 和原子属性(如果有的话)。价值保持不变,但失去了左值属性(地址可能不再被采用)。

如果左值具有不完整类型,则行为未定义。

如果左值指定一个自动存储持续时间的对象,其地址从未被采用,并且该对象未初始化(未使用初始化器声明并且在使用之前未对其进行分配),则行为是未定义的。

此转换将模拟对象的值从其位置的内存负载。

volatile int n = 1;int x = n;            // lvalue conversion on n reads the value of nvolatile int* p = &n; // no lvalue conversion: does not read the value of n

数组到指针的转换

数组类型的任何左值表达式,当在除。以外的任何上下文中使用时。

  • 作为操作符地址的操作数

  • 作为 sizeof 的操作数

  • 作为用于数组初始化的字符串文字

经历转换到非左值指针到它的第一个元素。

如果数组被声明为注册,则行为是未定义的。

int a[3], b[3][4];int* p = a;      // conversion to &a[0]int (*q)[4] = b; // conversion to &b[0]

函数指针转换

任何函数指示符表达式,当在除。以外的任何上下文中使用时。

  • 作为操作符地址的操作数

  • 作为sizeof的操作数

经过转换到非左值指针指向由表达式指定的函数。

int f(int);int (*p)(int) = f; // conversion to &f(***p)(1); // repeated dereference to f and conversion back to &f

隐式转换语义

隐式转换,无论是通过赋值还是通常的算术转换,都由两个阶段组成:

1)价值转化(如果适用)

2)下面列出的转换之一(如果它可以产生目标类型)

兼容的类型

将任何类型的值转换为任何兼容类型始终是不可操作的,并且不会更改表示形式。

uint8_t (*a)[10];         // if uint8_t is a typedef to unsigned charunsigned char (*b)[] = a; // then these pointer types are compatible

整数升级

整数推广是任意整数类型的值的隐式转换与秩小于或等于秩为int或类型_Bool,整型,符号int,unsigned int类型的位域的,以类型的值intunsigned int

如果int可以表示原始类型的整个值范围(或原始位域的值的范围),则将该值转换为类型int。否则,该值将转换为unsigned int

整数升级保持价值,包括符号:

int main(void) {   void f(); // old-style function declaration
   char x = 'a'; // integer conversion from int to char   f(x); // integer promotion from char back to int}void f(x) int x; {} // the function expects int

上面的 rank 是每个整数类型的属性,定义如下:

1)所有有符号整数类型的行列是不同的,并且随着它们的精度而增加:被签名的char的等级<短的等级<int的等级<long int的等级<long long 的等级 int

2)所有有符号整数类型的等级等于对应无符号整数类型的等级

3)任何标准整数类型的等级大于任何相同大小的扩展整数类型的等级(即,__int64 <等级长long int,但 long long 等级<由于规则而等于__int128等级(1))

4)char 的等级等于 signed char 的等级和 unsigned char 的等级

5)_Bool 的排名小于任何其他标准整数类型的排名

6)任何枚举类型的等级等于其兼容整数类型的等级

7)排名是传递性的:如果T1的等级<T2的等级和T2的等级<T3的等级,那么T1的等级<T3的等级

8)上面未涉及的扩展整数类型的相对排序的任何方面都是实现定义的

注意:整数升级只适用。

  • 作为通常算术转换的一部分(见上文)

  • 作为默认参数促销的一部分(参见上文)

  • 到一元算术运算符的操作数+和 -

  • 到一元位运算符〜的操作数

  • 移位运算符<<和>>的两个操作数

布尔转换

任何标量类型的值都可以隐式转换为_Bool。将等于零的值转换为0,将其他所有值转换为1

bool b1 = 0.5;              // b1 == 1 (0.5 converted to int would be zero)bool b2 = 2.0*_Imaginary_I; // b2 == 1 (but converted to int would be zero)bool b3 = 0.0 + 3.0*I;      // b3 == 1 (but converted to int would be zero)bool b4 = 0.0/0.0;          // b4 == 1 (NaN does not compare equal to zero)

整数转换

任何整数类型的值都可以隐式转换为任何其他整数类型。除了上述促销和布尔转换所涵盖的地方外,规则如下:

  • 如果目标类型可以表示源类型的整个值范围,则值不变

  • 否则,如果目标类型是无符号的,则将值2 b(其中b是目标类型中的位数)重复减去或添加到源值直到结果符合目标类型。换句话说,无符号整数实现模运算。

  • 否则,如果目标类型被签名,则行为是实现定义的(可能包括提升信号)

char x = 'a'; // int -> char, result unchangedunsigned char n = -123456; // target is unsigned, result is 192 (that is, -123456+483*256)signed char m = 123456;    // target is signed, result is implementation-defined

Real floating-integer conversions

任何实数浮点类型的有限值都可以隐式转换为任何整数类型。除了上述布尔转换覆盖的地方,规则是:

  • 小数部分被丢弃(截至零)。

    • 如果结果值可以用目标类型表示,则使用该值

    • 否则,行为是不确定的

int n = 3.14; // n == 3int x = 1e10; // undefined behavior for 32-bit int

任何整数类型的值都可以隐式转换为任何实数浮点类型。

  • 如果该值可以完全由目标类型表示,则该值不变

  • 如果值可以表示,但不能精确表示,则结果是最接近的较高值或最接近的较低值(换句话说,舍入方向是实现定义的),但是如果支持IEEE算术,舍入是最接近的。FE_INEXACT在这种情况下是否提出是没有具体说明的。

  • 如果该值不能表示,行为是未定义的,但如果支持IEEE算术,FE_INVALID则引发并且结果值未指定。

这种转换的结果可能比其目标类型指示的范围和精度更高(请参阅FLT_EVAL_METHOD

如果FE_INEXACT在浮点到整数转换中需要控制,rintnearbyint可以使用。

double d = 10; // d = 10.00float f = 20000001; // f = 20000000.00 (FE_INEXACT)float x = 1+(long long)FLT_MAX; // undefined behavior

实际浮点转换

任何实际浮动类型的值都可以隐式转换为任何其他实际浮动类型。

  • 如果该值可以完全由目标类型表示,则不会改变

  • 如果值可以表示,但不能精确表示,则结果是最接近的较高值或最接近的较低值(换句话说,舍入方向是实现定义的),但是如果支持IEEE算术,舍入是最接近的

  • 如果该值无法表示,则行为未定义

这种转换的结果可能比其目标类型指示的范围和精度更高(请参阅FLT_EVAL_METHOD

double d = 0.1; // d = 0.1000000000000000055511151231257827021181583404541015625float f = d;    // f = 0.100000001490116119384765625float x = 2*(double)FLT_MAX; // undefined

复杂的类型转换

任何复杂类型的值都可以隐式转换为任何其他复杂类型。实部和虚部分别遵循实际浮动类型的转换规则。

double complex d = 0.1 + 0.1*I;float complex f = d; // f is (0.100000001490116119384765625, 0.100000001490116119384765625)

虚构类型转换

任何虚构类型的值都可以隐式转换为任何其他虚构类型。虚部遵循实际浮动类型的转换规则。

double imaginary d = 0.1*_Imaginary_I;float imaginary f = d; // f is 0.100000001490116119384765625*I

真正复杂的转换

任何实际浮动类型的值都可以隐式转换为任何复杂类型。

  • 结果的实际部分取决于实际浮动类型的转换规则

  • 结果的虚部为正零(或非IEEE系统上的无符号零)

任何复杂类型的值都可以隐式转换为任何实际浮动类型。

  • 实部按照真实浮动类型的规则进行转换

  • 虚部被丢弃

注意:在复数到实数转换中,虚数部分的 NaN 不会传播到实际结果。

实际的虚拟转换

任何虚数类型的值都可以隐式转换为任何实数类型(整型或浮点型)。除目标类型为_Bool 之外,结果始终为正值(或无符号)零,在这种情况下,布尔转换规则适用。

任何实数类型的值都可以隐式转换为任何虚数类型。结果总是一个正的虚构的零。

复数 - 虚数转换

任何虚构类型的值都可以隐式转换为任何复杂类型。

  • 结果的实际部分是正的零

  • 结果的虚数部分遵循相应实际类型的转换规则

任何复杂类型的值都可以隐式转换为任何虚构类型。

  • 真正的部分被丢弃

  • 结果的虚数部分遵循相应实际类型的转换规则

double imaginary z = I * (3*I); // the complex result -3.0+0i loses real part, gives zero

指针转换

一个指针void可以使用以下语义隐式转换为指向对象类型的指针:

  • 如果指向对象的指针转换为指向 void 和指向的指针,则其值将与原始指针相等。

  • 没有其他担保提供

int* p = malloc(10 * sizeof(int)); // malloc returns void*

指向非限定类型的指针可以隐式转换为指向该类型限定版本的指针(换句话说,可以添加 const,volatile和 restrict 限定符。原始指针和结果比较相等。

int n;const int* p = &n; // &n has type int*

任何具有值的整数常量表达式0以及将值void*转换为0的整型指针表达式都可以隐式转换为任何指针类型(既指向对象又指向函数的指针)。结果是它的类型的空指针值,保证比较不等于该类型的任何非空指针值。这个整数或 void *表达式被称为空指针常量,标准库提供这个常量的一个定义作为宏NULL

int* p = 0;double* q = NULL;

笔记

尽管任何算术运算符中的有符号整数溢出都是未定义行为,但在整数转换中溢出有符号整数类型仅仅是未指定的行为。

另一方面,尽管任何算术运算符(和整数转换)中的无符号整数溢出是一个定义明确的操作,并遵循模算术规则,但浮点到整数转换中的无符号整数溢出是未定义的行为:可以转换为无符号整数的实际浮动类型的值是来自打开间隔(-1; Unnn_MAX + 1)的值。

unsigned int n = -1.0; // undefined behavior

指针和整数之间的转换(除了指向_Bool 的指针和整数常量表达式,值为零到指针)之间,指向对象的指针(除非指向 void 的指针或指向 void 的指针之外)以及指向函数的指针之间的转换函数具有兼容类型)从不隐含,并且需要一个演员操作符。

在指向函数的指针和指向对象的指针(包括 void *)或整数之间没有转换(隐式或显式)。

参考

  • C11 standard (ISO/IEC 9899:2011):

    • 6.3 Conversions (p: 50-56)

  • C99 standard (ISO/IEC 9899:1999):

    • 6.3 Conversions (p: 42-48)

  • C89/C90 standard (ISO/IEC 9899:1990):

    • 3.2 Conversions

上一篇:下一篇: