void fun()
{
// Essentially this is a function with an empty body
// And I don't care about () in a macro
// Because this is evil, regardless
#define printf(a, b) (printf)(a, b*2)
}
void main() // I know this is not a valid main() signature
{
int x = 20;
fun();
x = 10;
printf("%d", x);
}
我对#define行有疑问!你能不能给我一些链接文档来理解这行代码。答案是20。
答案 0 :(得分:2)
#define 定义预编译器宏在编译器执行任何操作之前由预处理器处理。 预处理器甚至不知道代码行是在函数内部还是外部。
通常在包含头文件后定义宏。 即在#include语句之后。
答案 1 :(得分:1)
预处理器宏不是实际C语言的一部分,宏和其他预处理器指令的处理是在编译器 1 之前完成的单独步骤。这意味着宏不遵循C的规则,特别是在作用域方面,宏总是“全局的”。
这意味着您认为在printf
函数中调用的main
函数实际上不是printf
函数,而是printf
宏< / EM> 强>
在预处理(和删除评论)后,您显示的代码将如下所示:
void fun()
{
}
void main()
{
int x = 20;
fun();
x = 10;
(printf)("%d", x*2);
}
发生的事情是printf
宏的调用被调用printf
函数替换。由于宏的第二个参数乘以2,输出将为10 * 2
,即20
。
这个程序说明了宏的一个主要问题:它很容易让程序看起来像普通的程序,但它做了一些意想不到的事情。定义实际评估为true
的宏false
很简单,相反,更改完全与true
或false
进行比较的含义。你应该从这样的例子中学到的唯一一件事是宏是多么糟糕,你永远不应该尝试使用宏来“重新定义”语言或标准函数。当使用很少和良好的宏是好的,将使C编程更容易。错误地使用,就像在这个例子中一样,它们会使代码变得不可读和不可维护。
1 预处理器曾经是在编译器程序之前运行的独立程序。现代编译器内置了预处理器步骤,但在解析实际C代码之前,它仍然是一个单独的步骤。
答案 2 :(得分:0)
让我以另一种方式提出这个问题。
printf()是一个内置的标准库函数,它将格式化的输出发送到stdout(您的控制台屏幕)。 printf()函数调用在程序运行期间执行。语法看起来像这样。
int printf(const char *format, ...)
但是你的这个程序在编译之前用你的宏替换了printf()函数。
void fun(){
#define printf(a, b) printf(a, b*2)
}
void main() {
int x = 20;
fun();
x = 10;
printf("%d", x);
}
所以会发生什么,在编译之前,编译器用你自己的用户定义的宏函数用两个参数替换内置函数调用:
所以x * 2的值= 20