复合表达式语句将限制x个
和年
,但仍可能与替换的表达式中出现的变量名冲突一
和b条
例如,如果最大值()
如下所示:
最大值(x++,y+1);
复合语句表达式的第一条语句将为:
自动x=(x++);
第二个语句将变为:
自动y=(y+1);
GCC的文档建议在标识符前面加下划线,以避免这些冲突。虽然我不支持,因为以下划线为前缀的标识符是保留的。
你可以使用临时雇员
/临时
后缀或前缀,或类似的东西。
编辑:我发现了一种更好的生成唯一名称的机制:
我们将使用C预处理器来帮助我们,并且cdecl 3.0版,它支持几乎所有的C和C++标准和扩展,以扩展宏:
美元cdeclcdecl>#define CONCAT2_EXPAND(a,b)a##bcdecl>#define CONCAT2(a,b)CONCAT2_EXPAND(a,b)cdecl>#define UNIQUE_NAME(前缀)CONCAT2(CONCAT2,前缀,_),__LINE__)cdecl>展开UNIQUE_NAME(var)UNIQUE_NAME(var)=>CONCAT2(CONCAT2,前缀,_),__LINE__)|前缀=>变量UNIQUE_NAME(var)=>CONCAT2(CONCAT2,var,_),__LINE__)|CONCAT2(CONCAT2(var,_),__LINE__)=>CONCAT2_EXPAND(a,b)||a=>CONCAT2(变量,_)||CONCAT2(var,_)=>CONCAT2_EXPAND(a,b)|||a=>变量|||b=>_||CONCAT2(var,_)=>CONCAT2_EXPAND(var、_)||||CONCAT2_EXPAND(变量,_)=>a##b|||CONCAT2_EXPAND(var,_)=>var##_||||CONCAT2_EXPAND(变量,_)=>变量_|||CONCAT2(var,_)=>var_||a=>变量_||b=>__LINE__||__LINE__=>42|| b=>42|CONCAT2(var_,42)=>CONCAT2_EXPAND(var_、42)||CONCAT2_EXPAND(var_,42)=>a##b||CONCAT2_EXPAND(var_,42)=>var_##42||CONCAT2_EXPAND(var_,42)=>var_42|CONCAT2(变量_,42)=>变量_42UNIQUE_NAME(变量)=>变量_42cdecl>
CONCAT2()
简单地串联其参数。CONCAT2_扩展()
是必需的,因为##
运算符不展开其操作数。唯一名称()
将传递给它的前缀与当前行号连接起来。
这个扩大
上面的命令显示了整个工作过程(实际输出非常丰富多彩。不幸的是,我无法在这里复制它)。这可能会生成一个非常独特的标识符。
我在找到这个方便的C/C++预处理器宏。这个博客是由写cdecl第3版的同一个人写的。cdecl的代码库也充分利用了这些宏。有关更多预处理器技巧,请参阅博客。
这些类似函数的宏都不能处理混合类型:
如果最大值()
被传递给签署
类型和未签名的
类型签署
类型很可能会转换为非常大的未签名的
类型。的当前3个版本最大值()
只适用于具有相同标志的类型。
对于长的
和整数
,很好。对于未签名的
和无符号长
,很好。
对于整数
和未签名的
,不太好。对于整数
和无符号长
,不太好。
溢流不是问题:
正如@Jonathan Leffer在关于StackOverflow问题的评论中所说:了解C11_通用
:
请注意§6.5.1.1一般选择¶3表示:泛型选择的控制表达式未求值。。因为它没有被计算,所以它不会溢出。这很有道理。控制表达式在编译时确定类型;溢出发生在运行时。
所以(a) +(b)
是正确的,除了@chux在评论中提到:
使用_泛型(((a)+(b),
类型永远不会小于整数
.
此解决方案不适用于MSVC:
根据C标准6.2.5.15,http://www.open-std.org/jtc1/sc22/wg14/www/docs/n869/n869.pdf.gz
三种类型烧焦
,带符号字符
,以及无符号字符
是集体的称为字符类型。实施应明确烧焦
到具有与以下两者相同的范围、表示和行为带符号字符
或无符号字符
. 32)
图表_最小值
,定义于<限值.h>
,将具有以下值之一0
或SCHAR_MIN公司
,这可以用来区分这两个选项。无论做出何种选择,烧焦
是与其他两个都不兼容。
但毫不奇怪,MSVC定义烧焦
和带符号字符
作为相同类型,这意味着在_通用
表达式,两者烧焦
和带符号字符
应兼容。我认为在这种情况下需要进行诊断。请参见:_通用
烧焦
,带符号字符
,无符号字符
在C11中不明显。该问题已在近4年前报告给微软,尚未修复,可能也不会修复。
为了避免这个问题,最简单的解决方案是使用原始的+ 0
隐式提升为整数
,而不检查任何烧焦
类型。