Tag: 语言律师

May C可以使用多种浮点格式进行评估吗?

C 2011 [N1570] 5.2.4.2.2 9说: 除了赋值和转换…之外,具有浮动操作数的运算符产生的值和通常算术转换以及浮动常量的值将被评估为其范围和精度可能大于该类型所需的格式。 这是否意味着可以使用一种格式评估实现中的所有浮点运算,或者可以使用更大范围和精度的格式评估每个运算? 如果用额外精度评估的A*B与用标称精度评估的A*B不同,后者将允许A*B == A*B评估为假。

什么是C中的复合类型?

从§6.2.7.5 (第66页): 示例给定以下两个文件范围声明: int f(int (*)(), double (*)[3]); int f(int (*)(char *), double (*)[]); 由此产生的函数的复合类型是: int f(int (*)(char *), double (*)[3]); 在示例上方,他们解释了复合类型是一种类型,与两种不同类型兼容。 我会直观地将“复合类型”这个短语理解为“结构和联合”,这似乎是偏离目标的。 什么是C中的复合类型,它用于什么? 有人可以详细解释上面的例子吗?

关于转换为整数常量表达式(在标准C中)

在标准C(我的意思是C99或C11)中,我们有所谓的整数常量表达式 ,它们是常量表达式,其操作数都是常量整数。 还有其他约束,以避免表达式中的逗号运算符。 但是,在某些特殊情况下,允许使用其他非整数对象(甚至是非常量对象)。 例如,如果将sizeof运算符应用于大小在转换时间中已知的对象,则允许将其作为整数常量表达式的一部分 (请注意, sizeof始终返回整数值)。 此外,有时也允许显式转换为整数类型。 标准C99建立以下规则: 标准C99,第6.6节(第6节): 整数常量表达式)应具有整数类型,并且只能具有整数常量,操作数,枚举常量,字符常量,结果为整数常量的sizeof表达式,以及作为强制转换的直接操作数的浮点常量。 标准C99 我的问题是: “浮动常数是演员的直接操作数”的确切含义是什么? 浮点常量类似于3.14e + 3,或者是0x2.11p-5。 也就是说,不是float类型的一般常量表达式,而只是浮点文字。 然后,我明白在上面的定义中只允许这样的事情: (int) 3.14 但是不允许涉及浮动文字的操作 。 这排除了以下情况: (int) -3.14 /* The minus sign is not part of the constant: it is an operator */ (int) (3.14) /* The parenthesis are an operator acting on the literal 3.14 */ […]

C标准是否要求n个元素数组的大小是元素大小的n倍?

C标准是否要求n个元素数组的大小是元素大小的n倍,可以通过显式语句还是通过严格的逻辑推理来满足其要求? 例如, int (*x)[5] = malloc(5 * sizeof **x); 无法为五个int的数组请求足够的空间? C 2011 [N1570] 6.5.3.4 7显示了将数组中的元素数量计算为sizeof array / sizeof array[0] 。 但是,例子不是标准的规范部分(根据前言第8段)。 6.2.5 20表示数组类型描述了具有特定类型的连续分配的非空对象集,但对所需的总内存没有提及。 这只是一个语言律师问题; 实际的实现是无关紧要的。 (为了安抚那些想要具体示例的人,假设一个C实现需要对大型数组进行额外的内存管理,因此创建一个数组需要创建一些额外的数据来帮助管理内存。)

C中的&* NULL定义良好吗?

C标准的哪个版本(如果有的话)是如下明确定义的? void foo(void) { char *nullPtr = NULL; &*nullPtr; } 请注意,我没有将结果分配给任何东西 – 第二行是一个简单的语句。 这应该是一个有明显答案的问题,但是(在这些问题上似乎经常发生的事情)我听到的同样多的人说答案“显然是未定义的”,因为“明确定义”。 在一个相当相关的说明,以下是什么? 应该foo产生c的读数? extern volatile char c; void bar(void) { volatile char *nonnullptr = &c; &*nonnullptr; } (相同问题的C ++版本: 在C ++中是否定义了&* NULL? )

将数据作为副作用提供有效类型吗?

假设我有一大块动态分配的数据: void* allocate (size_t n) { void* foo = malloc(n); … return foo; } 我希望将foo指向的数据用作特殊类型type_t 。 但是我想稍后这样做,而不是在分配期间。 为了给分配的数据一个有效的类型 ,我可以这样做: void* allocate (size_t n) { void* foo = malloc(n); (void) *(type_t*)foo; … return foo } 根据C11 6.5 / 6,这个左值访问应该是有效类型type_t : 对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型。 但是,行(void) *(type_t*)foo; 不包含任何副作用,因此编译器应该可以自由地优化它,我不希望它生成任何实际的机器代码。 我的问题是:上面的安全措施是什么? 是否将数据作为副作用提供有效类型? 或者通过优化代码,编译器是否也会优化掉有效类型的选择? 也就是说,使用上面的左值访问技巧,如果我现在调用上面这样的函数: int* i = allocate(sizeof(int)); *i = something; 这是否会导致严格的别名违规UB,或者是现在的有效类型int […]

C标准是否有缺陷报告的网站?

在我之前的问题中 ,讨论似乎意味着C标准可能存在缺陷,最重要的回答者的最后一句话进一步暗示: 该标准的作者只是忽略了这样说。 我知道C ++有一个在线网站,您可以在其中搜索缺陷报告,即这里是我搜索空指针常量 ,但C标准是否有类似的东西?

字节中的位数是否等于char类型中的位数?

C标准是否要求它? 是否有一个平台,其中一个字节中的位数不等于char类型中的位数?

C中的声明与定义

考虑一下代码: int main(void) { int a; } 据我所知, int a; 是一个定义,因为它会导致存储被保留。 引用C标准(N1570委员会草案 – 2011年4月12日): 6.7 / 5语义声明指定了一组标识符的解释和属性。 标识符的定义是该标识符的声明: – 对于一个对象,导致为该对象保留存储; … 问题出在这里:编译器可能会优化存储,因为我们没有使用变量。 然后是int a; 那么宣言呢? 如果我们在main(void)执行printf(“%p”, &a) ,那么现在编译器必须分配存储,因此声明/定义的概念取决于您以后是否使用标识符?

argv中指向字符串的指针是否可修改?

最近(2016年1月,如果问题持续时间足够长)我们有问题argv中的字符串是否可修改? 。 在这个答案的评论部分,我们(@ 2501和我)认为它是否真的是可修改的字符串 (例如**argv的示例字符)或指向字符串的指针 (示例指针是*argv )。 适当的标准报价来自C11标准草案N1570,§5.1.2.2.1/ 2: 参数argc和argv以及argv数组指向的字符串应由程序修改,并在程序启动和程序终止之间保留它们最后存储的值。 argv modifiable指向字符串的指针是什么?