(macro +1) 和 (1 + macro) 区别的原因
Reason for the difference between (macro +1) and (1 + macro)
一个宏(见下文)到return两个数字中较大的一个加1。但是,加法的效果不存在。
PS: 我也通过在宏中添加过多的括号进行了检查。
#define max(a,b) (a >= b ? a : b);
void main(){
int result = max(5,10) + 1; //result = 10
}
解决方案:
案例 1:
通过手动替换表达式中的宏(我认为就像预处理器所做的那样),加法正确执行。
result = (5 >= 10 ? 5 : 10) + 1; // Evaluates correctly to 11.
案例 2:
当操作数的顺序颠倒时,表达式也能正确求值。
result = 1 + max(5,10); //Evaluates correctly to 11.
为什么原始表达式没有按预期工作,而两个解决方案案例却可以?
您错误地将 ;
添加到您的宏中。所以展开其实是
void main(){
int result = (5 >= 10 ? 5 : 10); + 1;
}
这里你的+1
变成了一个什么都不做的单独语句,result
被初始化为10
。
顺便说一下,如果您使用 gcc 或 Clang,则有一个 -E
标志将 运行 实际的预处理器放在您的源代码上。上面的代码是运行ninggcc -E a.c
在你的代码上得到的
我还建议使用最大可能级别的警告进行编译。例如。 gcc -Wall -Wextra -Werror a.c
提示有问题:
a.c:2:6: error: return type of 'main' is not 'int' [-Werror=main]
2 | void main(){
| ^~~~
a.c: In function 'main':
a.c:3:28: error: statement with no effect [-Werror=unused-value]
3 | int result = max(5,10) + 1; //result = 10
| ^
a.c:3:9: error: unused variable 'result' [-Werror=unused-variable]
3 | int result = max(5,10) + 1; //result = 10
| ^~~~~~
cc1.exe: all warnings being treated as errors
因为你在宏后面加了分号
#define max(a,b) (a >= b ? a : b);
^^^
删除它。
宏应该这样写
#define max(a,b) ( ( a ) >= ( b ) ? ( a ) : ( b ) )
所以在第一种情况下你实际上有
int result = ( 5 >= 10 ? 5 : 10 );
+ 1;
如果你会放置声明
int result = max(5,10) + 1;
在函数 main 之前的文件作用域中,编译器会报错,因为会有语句
+ 1;
并且您不能在文件范围内放置语句。
至于这个说法
result = 1 + max(5,10);
然后扩展为两个语句
result = 1 + ( 5 >= 10 ? 5 : 10 );
;
也就是还有一个无效的空语句。
注意根据C标准,不带参数的函数main应该声明为
int main( void )
一个宏(见下文)到return两个数字中较大的一个加1。但是,加法的效果不存在。
PS: 我也通过在宏中添加过多的括号进行了检查。
#define max(a,b) (a >= b ? a : b);
void main(){
int result = max(5,10) + 1; //result = 10
}
解决方案: 案例 1:
通过手动替换表达式中的宏(我认为就像预处理器所做的那样),加法正确执行。
result = (5 >= 10 ? 5 : 10) + 1; // Evaluates correctly to 11.
案例 2: 当操作数的顺序颠倒时,表达式也能正确求值。
result = 1 + max(5,10); //Evaluates correctly to 11.
为什么原始表达式没有按预期工作,而两个解决方案案例却可以?
您错误地将 ;
添加到您的宏中。所以展开其实是
void main(){
int result = (5 >= 10 ? 5 : 10); + 1;
}
这里你的+1
变成了一个什么都不做的单独语句,result
被初始化为10
。
顺便说一下,如果您使用 gcc 或 Clang,则有一个 -E
标志将 运行 实际的预处理器放在您的源代码上。上面的代码是运行ninggcc -E a.c
在你的代码上得到的
我还建议使用最大可能级别的警告进行编译。例如。 gcc -Wall -Wextra -Werror a.c
提示有问题:
a.c:2:6: error: return type of 'main' is not 'int' [-Werror=main]
2 | void main(){
| ^~~~
a.c: In function 'main':
a.c:3:28: error: statement with no effect [-Werror=unused-value]
3 | int result = max(5,10) + 1; //result = 10
| ^
a.c:3:9: error: unused variable 'result' [-Werror=unused-variable]
3 | int result = max(5,10) + 1; //result = 10
| ^~~~~~
cc1.exe: all warnings being treated as errors
因为你在宏后面加了分号
#define max(a,b) (a >= b ? a : b);
^^^
删除它。
宏应该这样写
#define max(a,b) ( ( a ) >= ( b ) ? ( a ) : ( b ) )
所以在第一种情况下你实际上有
int result = ( 5 >= 10 ? 5 : 10 );
+ 1;
如果你会放置声明
int result = max(5,10) + 1;
在函数 main 之前的文件作用域中,编译器会报错,因为会有语句
+ 1;
并且您不能在文件范围内放置语句。
至于这个说法
result = 1 + max(5,10);
然后扩展为两个语句
result = 1 + ( 5 >= 10 ? 5 : 10 );
;
也就是还有一个无效的空语句。
注意根据C标准,不带参数的函数main应该声明为
int main( void )