C语言 将函数定义为宏

yxyvkwin  于 2023-02-21  发布在  其他
关注(0)|答案(4)|浏览(151)

我试图理解将函数定义为宏,我有以下代码,我不确定我是否理解:

#define MAX(i, limit) do \      
{ \     
    if (i < limit) \    
    { \ 
        i++; \
    } \ 
} while(1)      
        
void main(void)     
{       
    MAX(0, 3);  
}

据我所知,它试图将MAX定义为两个数之间的区间,但是无限循环的意义何在?
我曾尝试将MAX的值存储在main函数内的变量中,但它显示错误消息expected an expression

7xzttuei

7xzttuei1#

  • 我目前在软件开发实习,并试图学习嵌入式C,因为这是一个新的领域,我。这是一个练习,问我下面的代码将做什么。我很困惑,因为我从来没有见过这样写的函数 *

你很困惑,因为这是一个陷阱问题。发布的代码没有任何意义。MAX宏确实扩展为无限循环,由于它的第一个参数是一个文本值,i++扩展为0++,这是一个语法错误。
要吸取的教训是:宏是混乱的、容易出错的,并且不应该被用来替换函数。

jtw3ybtb

jtw3ybtb2#

你必须明白,你的代码进入编译器之前,它首先要通过一个预处理器。它基本上改变了你的文本代码。它改变代码的方式是由预处理器指令控制的(以#开始的行,例如#include#define,...)。
在您的示例中,您使用了#define指令,预处理器在任何地方找到MAX(i, limit)都将替换为它的定义。
预处理器的输出也是一个文本文件,但是做了一些修改。在您的示例中,预处理器将用

do
{
    if (0 < 3)  
    {
        0++;
    }
} while(1)
    • 现在**预处理器输出到这样的编译器。

因此,在#define中编写函数与编写普通函数void max(int i, int limit) { ... }是不同的。

dgtucam1

dgtucam13#

假设你有很多这样的语句

if(a < 10) a++;

if(b < 100) b++;

if(c < 1000) c++;

在一篇评论中,@the busybee将这种模式称为“饱和增量器”。
当你在代码中看到一个重复的模式时,你自然会倾向于封装这个模式。有时候这是个好主意,或者有时候如果尝试封装它会使事情变得更糟,那么就离开重复也没关系。
封装这种特殊模式的一种方法--我不会说我认为这是不是一种好方法--是定义一个类似函数的宏:

#define INCR_MAX(var, max) if(var < max) var++

那你可以说

INCR_MAX(a, 10);
INCR_MAX(b, 100);
INCR_MAX(c, 1000);

要将其作为类似函数的宏的一个原因是(与真函数相反)的一个特点是,宏可以“修改其参数”--在本例中,无论您给它的变量名是var--这是真函数所不能做到的。(也就是说,如果饱和增量器是一个true函数,那么根据设置方式的不同,你必须调用incr_max(&a, 10)a = incr_max(a, 10)。)
然而,类似函数的宏和末尾的分号有一个问题,我不打算在这里解释整个问题;有一个关于它的big long previous SO question
应用另一个问题的教训,“改进的”INCR_MAX宏将是

#define INCR_MAX(var, max) do { if(var < max) var++; } while(0)

最后,在你的练习和这个SO问题之间的某个地方,结尾的while(0)不知何故被改成了while(1),这几乎是一个无意的错误,因为while(1)在这个上下文中没有任何意义。

lztngnrs

lztngnrs4#

是的,你不明白是有原因的--这是垃圾。
经过预处理后,代码为

void main(void)
{
  do 
  {
    if ( 0 < 3 )
    {
      0++;
    }
  } while(1);
}

是的,不知道这个东西 * 应该 * 做什么。名称MAX暗示它应该计算两个参数中较大的一个,a la

#define MAX(a,b) ((a) < (b) ? (b) : (a))

但很明显这不是它所做的,它没有定义两个数之间的间隔,它试图将第一个参数的值设置为第二个参数的值,但是用一种毫无意义的方式。
有三个问题(技术上是四个):

  • 编译器将yak on 0++-常量不能是++--运算符的操作数;
  • 如果i或者limit是表达式,比如MAX(i+1, i+5),你会遇到同样的问题,比如++运算符,你会遇到优先级问题;
  • 假设你解决了这些问题,你仍然有一个无限循环;

第四个(技术)问题是......使用宏作为函数。我知道,这是嵌入式世界,嵌入式世界希望最小化函数调用开销。这就是inline函数说明符应该给你买的东西,这样你就不必经历这种心痛。
但是,好吧,也许您正在使用的系统可用的编译器不支持inline,所以您必须完成这个练习。
但是你必须去找给你这个代码的人,礼貌而恭敬地问,“这是什么垃圾?”

相关问题