实现定义的行为

概述

C 标准描述了语言语法,标准库提供的功能,以及符合 C 处理器(粗略地说,编译器)和符合 C 程序的行为。就行为而言,大多数标准规定了程序和处理器的特定行为。另一方面,某些操作具有显式或隐式的未定义行为 - 总是要避免这种操作,因为你不能依赖于它们的任何内容。在这两者之间,存在各种实现定义的行为。这些行为可能因 C 处理器,运行时和标准库(统称为实现) 而异 ** ),但它们对于任何给定的实现都是一致和可靠的,并且符合实现的文档记录了它们在这些领域中的每一个。

程序依赖于实现定义的行为有时是合理的。例如,如果程序无论如何都是特定于特定操作环境的,那么依赖于实现定义的行为通常对于该环境的公共处理器来说不太可能成为问题。或者,可以使用条件编译指令来选择适合于正在使用的实现的实现定义的行为。在任何情况下,必须知道哪些操作具有实现定义的行为,以便避免它们或者是否以及如何使用它们做出明智的决定。

这些评论的平衡构成了 C2011 标准中规定的所有实施定义的行为和特征的列表,并参考了该标准。他们中的许多人使用标准的术语 。其他一些更普遍地依赖于标准的上下文,例如将源代码转换为程序的八个阶段,或托管和独立实现之间的差异。可能特别令人惊讶或值得注意的一些以粗体字体呈现。并非所有描述的行为都受到早期 C 标准的支持,但一般来说,它们在支持它们的所有标准版本中都具有实现定义的行为。

程序和处理器

一般

  • 一个字节中的位数3.6 / 3 )。至少 8,可以用宏 CHAR_BIT 查询实际值。

  • 哪些输出消息被视为诊断消息3.10 / 1

来源翻译

  • 物理源文件多字节字符映射到源字符集( 5.1.1.2/1 )的方式。

  • 在翻译阶段 3( 5.1.1.2/1 ) 期间,非换行空格的非空序列是否被单个空格替换

  • 字符串常量中的字符文字和字符转换的执行集字符(在转换阶段 5 期间),否则没有相应的字符( 5.1.1.2/1 )。

操作环境

  • 确定要发出的诊断消息的方式( 5.1.1.3/1 )。

  • 在独立实现( 5.1.2.1/1 ) 中启动时调用的函数的名称和类型。

  • 在指定的最小集合( 5.1.2.1/1 ) 之外的独立实现中可以使用哪些库工具。

  • 程序终止在独立环境中的影响( 5.1.2.1/2 )。

  • 在托管环境中,除 int main(int argc, char *arg[])int main(void)5.1.2.2.1 / 1 ) 之外的 main() 功能的任何允许签名。

  • 托管实现定义 main()5.1.2.2.1 / 2 ) 的第二个参数指向的字符串的方式。

  • 为了第 5.1.2.3 节 (程序执行)和 7.21.3 (文件)( 5.1.2.3/7 ) 的目的,什么构成交互设备

  • 对优化实现( 5.1.2.3/10 ) 中的中断处理程序例程引用的对象的任何限制。

  • 在独立实现中,是否支持多个执行线程( 5.1.2.4/1 )。

  • 执行字符集成员的值( 5.2.1 / 1 )。

  • char 值对应于定义的字母转义序列( 5.2.2 / 3 )。

  • 整数和浮点数字限制和特征5.2.4.2/1 )。

  • 浮点算术运算的准确性以及标准库从内部浮点表示到字符串表示的转换( 5.2.4.2.2 / 6 )。

  • FLT_ROUNDS 的值,它编码默认的浮点舍入模式( 5.2.4.2.2 / 8 )。

  • 圆形行为的特征是 FLT_ROUNDS 的支持值大于 3 或小于 -1( 5.2.4.2.2 / 8 )。

  • FLT_EVAL_METHOD 的值,它表征浮点评估行为( 5.2.4.2.2 / 9 )。

  • 行为的特征是任何支持的 FLT_EVAL_METHOD 值小于 -1(5.2.4.2.2 / 9 )。

  • FLT_HAS_SUBNORMDBL_HAS_SUBNORMLDBL_HAS_SUBNORM 的值,表征标准浮点格式是否支持次正规数( 5.2.4.2.2 / 10

类型

  • 尝试(间接)从与该对象关联的线程之外的线程访问具有线程存储持续时间的对象的结果( 6.2.4 / 4

  • 已分配基本执行集之外的字符的 char 的值( 6.2.5 / 3 )。

  • 支持的扩展有符号整数类型(如果有)( 6.2.5 / 4 )以及用于标识它们的任何扩展关键字。

  • char 是否具有与 signed charunsigned char6.2.5 / 15相同的表示和行为。可以用 CHAR_MIN 查询,如果 char 未签名或签名,则分别为 0SCHAR_MIN

  • 对象表示中字节的数量,顺序和编码,除非标准明确指定( 6.2.6.1/2 )。

  • 在任何给定情况下,三种公认的整数表示形式中的哪一种适用,以及整数对象的某些位模式是否是陷阱表示6.2.6.2/2 )。

  • 每种类型的对齐要求( 6.2.8 / 1 )。

  • 是否支持以及在何种情况下支持任何扩展比对( 6.2.8 / 3 )。

  • 支持的扩展对齐集6.2.8 / 4 )。

  • 任何扩展有符号整数类型相对于彼此的整数转换等级( 6.3.1.1/1 )。

  • 将超出范围的值分配给有符号整数6.3.1.3/3 )的效果。

  • 当在范围内,但不可表示的值被分配到一个浮点对象,如何存储在对象可表示的值是从所述两个最接近的可表示的值(选择之间 6.3.1.4/2 ; 6.3.1.5/1 ; 6.4.4.2 / 3 )。

  • 将整数转换为指针类型的结果,但值为 06.3.2.3/5 )的整数常量表达式除外。

来源表格

  • #pragma 指令中识别标题名称标记的位置( 6.4 / 4 )。

  • 字符,包括多字节字符,下划线,非重音拉丁字母,通用字符名称和可能出现在标识符中的十进制数字( 6.4.2.1/1 )。

  • 标识符中的重要字符数6.4.2.1/5 )。

  • 除了一些例外,整数字符常量中的源字符映射到执行集字符的方式( 6.4.4.4/2 ; 6.4.4.4/10 )。

  • 当前区域设置用于计算宽字符常量的值,以及许多此类常量的转换的大多数其他方面( 6.4.4.4/11 )。

  • 是否可以连接带有不同前缀的宽字符串文字标记,如果是,则处理生成的多字节字符序列( 6.4.5 / 5

  • 在转换阶段 7 期间使用的语言环境将宽字符串文字转换为多字节字符序列,以及当结果在执行字符集中无法表示时的值( 6.4.5 / 6 )。

  • 标题名称映射到文件名的方式( 6.4.7 / 2 )。

评估

  • 不使用 FP_CONTRACT 时是否以及如何收缩浮点表达式( 6.5 / 8 )。

  • sizeof_Alignof 运算符的结果值6.5.3.4/5 )。

  • 指针减法的结果类型的大小( 6.5.6 / 9 )。

  • 右移有符号整数的结果为负值6.5.7 / 5 )。

运行时行为

  • register 关键字有效的程度( 6.7.1 / 6 )。

  • 声明为 int 的位域类型是否与 unsigned intsigned int6.7.2 / 5 )的类型相同。

  • 除了可选合格的 _Boolsigned intunsigned int 之外,还有哪些类型的位域可以采用; 位域是否可能具有原子类型( 6.7.2.1/5 )。

  • 关于实现如何布局位域存储的方面( 6.7.2.1/11 )。

  • 结构和联合的非位域成员的对齐( 6.7.2.1/14 )。

  • 每种枚举类型的基础类型( 6.7.2.2/4 )。

  • 是什么构成了对天赋资格对象的访问6.7.3 / 7 )。

  • inline 函数声明的有效性( 6.7.4 / 6 )。

预处理器

  • 字符常量是否在预处理器条件中以与普通表达式相同的方式转换为整数值,以及单字符常量是否可能具有负值( 6.10.1 / 4 )。

  • 这些位置搜索了 #include 指令( 6.10.2 / 2-3 )中指定的文件。

  • 从多标记 #include 指令( 6.10.2 / 4 ) 的标记形成标题名称的方式。

  • #include 嵌套的限制( 6.10.2 / 6 )。

  • 是否在\之前插入了\字符,在预处理器的 # 运算符( 6.10.3.2/2 ) 的结果中引入了通用字符名称。

  • STDC6.10.6 / 1 ) 之外的 pragma 的 #pragma 预处理指令的行为。

  • 如果没有翻译日期或时间,则 __DATE____TIME__ 宏的值可用( 6.10.8.1/1 )。

  • 如果未定义宏 __STDC_ISO_10646__,则用于 wchar_t 的内部字符编码( 6.10.8.2/1 )。

  • 如果未定义宏 __STDC_UTF_32__,则用于 char32_t 的内部字符编码( 6.10.8.2/1 )。

标准库

一般

  • 断言失败时发出的消息格式( 7.2.1.1/2 )。

浮点环境功能

  • 除标准( 7.6 / 6 ) 定义之外的任何其他浮点异常。

  • 任何额外的浮点舍入模式超出标准( 7.6 / 8 ) 定义的模式。

  • 除标准( 7.6 / 10 ) 定义的任何其他浮点环境。

  • 浮点环境访问开关的默认值( 7.6.1 / 2 )。

  • fegetexceptflag()7.6.2.2/1 ) 记录的浮点状态标志的表示。

  • feraiseexcept() 函数是否会在引发溢出下溢浮点异常( 7.6.2.3/2 ) 时另外引发不精确的浮点异常。

与区域设置相关的功能

  • setlocale() 支持的语言环境字符串除了 C7.11.1.1/3 )。

数学函数

  • FLT_EVAL_METHOD 宏具有与 0127.12 / 2 ) 不同的值时,由 float_tdouble_t 表示的类型。

  • 任何受支持的浮点分类超出标准( 7.12 / 6 ) 定义的分类。

  • math.h 返回的值在域错误( 7.12.1 / 2 ) 的情况下起作用。

  • 当极点错误( 7.12.1 / 3 )时,math.h 返回的值起作用。

  • 当结果下溢时 math.h 返回的值,以及 errno 是否设置为 ERANGE 以及是否在这些情况下引发浮点异常的方面( 7.12.1 / 6 )。

  • FP 收缩开关的默认值( 7.12.2 / 2 )。

  • 当第二个参数为 0( 7.12.10.1/3 ) 时,fmod() 函数是返回 0 还是引发域错误。

  • remainder() 函数的第二个参数为 0( 7.12.10.2/3 ) 时,它是返回 0 还是引发域错误。

  • remquo() 函数( 7.12.10.3/2 ) 计算的商模数中的有效位数。

  • remquo() 函数的第二个参数为 0( 7.12.10.3/3 ) 时,它是返回 0 还是引发域错误。

信号

  • 完整的支持信号集,它们的语义和默认处理( 7.14 / 4 )。

  • 当引发信号并且存在与该信号相关联的自定义处理程序时,在处理程序的执行期间( 7.14.1.1/3 ) 阻塞哪些信号(如果有的 )。

  • SIGFPESIGILLSIGSEGV 以外的哪些信号导致从自定义信号处理程序返回时的行为未定义( 7.14.1.1/3 )。

  • 最初配置哪些信号被忽略(无论其默认处理如何; 7.14.1.1/6 )。

  • NULL 扩展的特定空指针常量( 7.19 / 3 )。

文件处理功能

  • 文本流的最后一行是否需要终止换行符( 7.21.2 / 2 )。

  • 自动附加到二进制流的空字符数( 7.21.2 / 3 )。

  • 以附加模式( 7.21.3 / 1 ) 打开的文件的初始位置。

  • 是否在文本流上写入会导致流被截断( 7.21.3 / 2 )。

  • 支持流缓冲( 7.21.3 / 3 )。

  • 是否实际存在零长度文件( 7.21.3 / 4 )。

  • 组成有效文件名的规则( 7.21.3 / 8 )。

  • 同一文件是否可以同时打开多次( 7.21.3 / 8 )。

  • 多字节字符编码的性质和选择( 7.21.3 / 10 )。

  • 当目标文件打开时,remove() 的行为将起作用( 7.21.4.1/2 )。

  • 当目标文件已存在时,rename() 的行为( 7.21.4.2/2 )。

  • 在程序异常终止的情况下,是否删除通过 tmpfile() 函数创建的文件( 7.21.4.3/2 )。

  • 哪种模式在 freopen()7.21.5.4/3 ) 允许的情况下发生变化。

I / O 功能

  • printf() - 族函数( 7.21.6.1/8 ) 产生哪些允许的无限和非数字 FP 值的表示。

  • printf()-family 函数( 7.21.6.1/8 ) 格式化指针的方式。

  • - 字符出现在 [ 字段的扫描列表的内部位置时,scanf()-family 的行为起作用( 7.21.6.2/12 )。

  • scanf() 家族的大部分方面都是为了处理 p 领域( 7.21.6.2/12 )。

  • fgetpos() 在失败时设置的 errno 值( 7.21.9.1/2 )。

  • fsetpos() 在失败时设置的 errno 值( 7.21.9.3/2 )。

  • ftell() 设置的 errno 值失败( 7.21.9.4/3 )。

  • 关于 NaN 格式的一些支持方面的 strtod()-family 函数的含义( 7.22.1.3p4 )。

  • 当结果下溢时,strtod()-family 函数是否将 errno 设置为 ERANGE7.22.1.3/10 )。

内存分配功能

  • 当请求的字节数为 0( 7.22.3 / 1 ) 时,内存分配功能的行为。

系统环境功能

  • 执行什么清理(如果有)以及在调用 abort() 函数时返回到主机 OS 的状态( 7.22.4.1/2 )。

  • 调用 exit() 时,主机环境返回什么状态( 7.22.4.4/5 )。

  • 调用 _Exit() 时,打开流的处理以及返回主机环境的状态( 7.22.4.5/2 )。

  • 可通过 getenv() 访问的环境名称集和改变环境的方法( 7.22.4.6/2 )。

  • system() 函数的返回值( 7.22.4.8/3 )。

日期和时间功能

  • 当地时区和夏令时( 7.27.1 / 1 )。

  • 时间范围和精度可通过 clock_ttime_t7.27.1 / 4 ) 类型表示。

  • 时代的开始,作为 clock() 函数返回的时间的参考( 7.27.2.1/3 )。

  • 作为 timespec_get() 函数返回的时间的参考的时期的开始(当时基是 TIME_UTC; 7.27.2.5/3 )。

  • strftime() 替换 C 语言环境中的%Z 转换说明符( 7.27.3.5/7 )。

宽字符 I / O 功能

  • wprintf() 系列函数( 7.29.2.1/8 ) 生成了无限和非数字 FP 值的哪些允许表示。

  • wprintf()-family 函数( 7.29.2.1/8 ) 格式化指针的方式。

  • - 字符出现在 [ 字段的扫描列表的内部位置时,wscanf()-family 的行为起作用( 7.29.2.2/12 )。

  • wscanf() 家族的大多数方面都在处理 p 领域( 7.29.2.2/12 )。

  • 关于 NaN 格式的一些支持方面的 wstrtod()-family 函数的含义( 7.29.4.1.1 / 4 )。

  • 当结果下溢时,wstrtod()-family 函数是否将 errno 设置为 ERANGE7.29.4.1.1 / 10 )。