Tag: 语言律师

是否存在EOF!= -1或WEOF!= -1的常见C环境

C标准使用以下语言定义EOF和WEOF : 7.21.1输入/输出 – 简介 头文件定义了几个宏,并声明了三种类型和许多用于执行输入和输出的函数。 … EOF 它扩展为一个整数常量表达式,类型为int,负值,由几个函数返回,表示文件结束,即不再有来自流的输入; … 7.21.1扩展的多字节和宽字符实用程序 – 简介: 头文件定义了四个宏,并声明了四种数据类型,一个标记和许多函数。 … wint_t 这是一个整数类型,默认情况下,参数提升不变,可以保存与扩展字符集成员对应的任何值,以及至少一个与扩展字符集的任何成员不对应的值 WEOF 扩展为类型为wint_t的常量表达式,其值与扩展字符集的任何成员都不对应。(328)本子条款中的若干函数接受(并返回)它以指示文件结束,即,没有来自流的输入。 它还用作宽字符值,与扩展字符集的任何成员都不对应。 328)宏观WEOF的值可能与EOF的值不同,不必为负值。 EOF是一个负值,它是getc()可以返回的唯一负值。 我已经看到它通常定义为(-1) ,同样WEOF定义为((wint_t)-1) 。 是否有任何常见的C环境,其中这些宏中的任何一个被定义为不同的东西? 标准委员会有什么理由留下不同价值的可能性,特别是对WEOF的非负价值?

具有静态存储持续时间的常量对象和相等的常量初始化器是否可以合并?

考虑两个具有静态存储持续时间和相等的常量初始化器的对象: static const int a = 50; static const int b = 50; 编译器是否有效组合这些&a == &b ? (对于上下文,我考虑使用静态常量对象来获取唯一地址以用作标记指针值。如果编译器合并这些对象是合法的,并且我对两个这样的对象使用相同的常量值,那么地址可以是平等的,我不能用它们作为哨兵价值。)

数组可以有尾随填充吗?

很明显,C中的数组不能在它们的元素之间插入填充 。 但是,是否有任何规则说他们不能在整个数组的末尾添加尾随填充? 即,这个计划保证在各地给出相同的结果吗? #include int main(void) { typedef char a[3]; typedef ab[3]; printf(“%zu %zu\n”, sizeof(a), sizeof(b)); // -> 3 9 } 据我所知,在一个误导的优化尝试中添加一个或五个大小的尾随字节,可能不会破坏数组访问规则( b[1][1]仍然完全映射到*(&b + sizeof(a) * 1 + 1)无论其包含a对象的大小如何,并且访问超出包含的a的长度仍然是UB)。 我在C标准中找不到任何地方,它实际上直接说数组的大小是元素类型的大小乘以元素的数量。 6.5.3.4只说sizeof返回数组中的“字节数”(它确实给出了sizeof array / sizeof array[0]作为代码示例,但它只是一个例子 – 它并没有说它必须工作 ,它没有提供任何细节)。 隐式保证对于编写依赖于精确数据布局的可移植代码非常有用,例如传递打包的RGB值: typedef uint8_t RGB[3]; RGB * data = …; glColorPointer(3, GL_UNSIGNED_BYTE, 0, data); (好的,所以OpenGL可以接受步幅值,所以这是一个不好的例子,但你明白了) 就此而言,我从广泛的概念(甚至是标准中的例子)中假设你可以得到带有sizeof的数组元素的数量,这可能在任何地方都适用 – […]

什么促销类型用于switch-case表达式比较?

使用不同的编译器编译时,以下程序打印“unknown”。 为什么会这样? #include “stdio.h” const char OPTION = (char)(unsigned char)253; int main(int argc, char* argv[]) { unsigned char c = 253; switch (c) { case OPTION: printf(“option\n”); break; default: printf(“unknown\n”); break; } return 0; } 在查看C ++标准(N3690 2013-05-05)时,我看到了一个switch子句: 6.4.2 switch语句 2条件应为整数类型,枚举类型或类类型。 如果是类类型,则将条件在上下文中隐式转换(第4节)为整数或枚举类型。 执行整体促销。 switch语句中的任何语句都可以用一个或多个case标签标记,如下所示: case constant-expression : 其中constant-expression应为切换条件的提升类型的转换常量表达式(5.19)。 在转换为提升类型的开关条件后,同一开关中的两个shell常量应具有相同的值。 引用的转换条款: 4标准转换 2 [注意:具有给定类型的表达式将在多个上下文中隐式转换为其他类型: […] – […]

C99 VLA尺寸确定和尺寸操作员

我写了以下内容作为关于sizeof及其关于C99 VLA的行为的问题的答案的一部分: 有意识地创建一个案例,其中count_of的语义对于VLA count_of会有所不同,但可能难以创建可读,易于理解/可维护且有用的案例(我没有尝试过)。 在考虑了这个之后,我不确定这个陈述是否真的如此。 要首先创建VLA,编译器必须首先确定VLA所需的空间量。 对于sizeof ,我们知道 如果操作数的类型是可变长度数组类型,则计算操作数; 否则,不评估操作数,结果是整数常量。 (6.5.3.4/2) 虽然VLA大小显然是运行时确定,但在评估VLA声明符的大小表达式后(如果有的话,包括任何副作用): 变长数组类型的每个实例的大小在其生命周期内不会改变。 如果size表达式是sizeof运算符的操作数的一部分,并且更改size表达式的值不会影响运算符的结果,则无法指定是否计算size表达式。 (6.7.5.2/2) 所以,给定 #define count_of(arr) (sizeof(arr)/sizeof(arr[0])) 有没有像这样的宏的实际有效行为对于VLA而不是数组大小表达式是一个常量表达式(即一个普通的C99前固定大小数组)的数组声明的情况?

在函数调用中,运算符是什么,操作数是什么?

我试图理解C语言的一些基础知识.CRC编程语言说 函数调用是一个后缀表达式 ,称为函数指示符,后跟括号,其中包含一个可能为空的逗号分隔的赋值表达式列表(Par.A7.17),它们构成函数的参数。 在函数调用中,运算符是什么,操作数是什么? 是()运营商? 函数名是操作数吗? 是()操作数内的参数? 函数指示符是函数调用的同义词吗? 谢谢。

带C ++的extern C是否避免了在C中合法而不是C ++的未定义行为?

如果将extern C it与C ++文件一起使用,是否允许在C ++中未定义的已定义C行为? blah.h extern “C” { struct x { int blah; char buf[]; }; char * get_buf(struct x * base); struct x * make_struct(int blah, int size); } some_random.cpp #include “blah.h” … x * data=make_struct(7, 12); std::strcpy(get_buf(data), “hello”); 在C的灵活数组成员中使用定义的行为,在使用这种方式时定义了行为吗?

错误的参数类型为定义为宏的标准库函数

这是示例代码: #include int main(void) { isalpha(“X”); } 我的问题是:此代码是违反约束的吗? 同样,如果不执行诊断,是不符合的实现吗? 动机:即使在符合规范的代码中,多个主要编译器也不会对此代码发出警告。 C11 6.5.2.2/2涵盖了将char *传递给具有原型期望int的函数是违反约束的情况。 但是,我不清楚7.1.4中允许将库函数另外定义为宏的规定是否取代了6.5.2.2/2的要求。 脚注187表明该宏隐藏了原型,但脚注是非规范性的。 代码(isalpha)(“X”); 确实给出了诊断。

对于使用extern的新声明,如何解决多个先前声明?

第三个x应该引用什么: #include static char x = ‘1’; int main(void) { char x = ‘2’; { extern char x; printf(“%c\n”, x); } } 这出现在这个答案中 ,并且: 在Apple LLVM 9.1.0 clang-902-0.39.2中, extern char x表示第一个x ,并且打印“1”。 GCC 8.2不接受此源文本。 ,抱怨:“错误:变量先前声明’静态’重新声明’extern’”。 C 2018 6.2.2 4说: 对于在该标识符的先前声明可见的范围内使用存储类说明符extern声明的标识符,如果先前声明指定内部或外部链接,则后面声明中的标识符的链接与链接相同在先前声明中指明。 如果没有先前声明可见,或者先前声明未指定链接,则标识符具有外部链接。 由于x有两个先前声明,因此以下每个“if”子句的条件为真,第一个用于第一个先前声明,第二个用于第二个先前声明: …如果先前的声明指定内部或外部链接,则后面声明中的标识符的链接与先前声明中指定的链接相同。 …如果先前声明未指定链接,则标识符具有外部链接。 Clang在这里的行为与使用第一个子句一致,因此第三个x具有内部链接并且引用与第一个x相同的对象。 GCC在这里的行为与使用第二个子句一致,因此第三个x具有外部链接并且与具有内部链接的第一个x冲突。 C标准是否为我们提供了解决这些问题的方法?

NaN对Bool的转换:对还是错?

C ++规范的哪一部分或IEEE浮点规范声明NaN值应该转换为true而不是false? 如果我查看C ++标准部分4.12布尔转换它说: 零值,空指针值或空成员指针值转换为false; 任何其他值都转换为true。 现在IEEE浮动说NaN将false与任何其他值进行比较。 因此NaN是真还是假取决于你如何进行比较(见下文)。 因此,我认为必须明确提及。 value == 0 ? false : true value != 0 ? true : false 现在,转换为整数怎么样? 下面的简短程序显示转换为整数的变量NAN导致最小整数,而常量转换为0(使用GCC)。 这看起来很奇怪。 #include #include void write( double r, int i, bool b ) { std::cout << r << " == " << i << " == " << (b ? "True" […]