一段代码引起的思考-------printf

本文通过两个示例探讨了C语言中整型(int)到浮点型(float)及双精度浮点型(double)的自动类型转换过程。揭示了在printf函数调用过程中,参数如何从32位的int类型转换为64位的double类型,并解释了由此产生的意外输出结果的原因。

看一小段代码:

#include <stdio.h>

 

int main()

{

       inta =5;

       printf("%f\n" a);

       return0;

}

在vc6.0和gcc中结果都是0.000000,为什么呢?

这得从int和float的转换说起,我们知道int是4 byte(32位),float也是4 byte,但是printf函数在将参数以单精度浮点数打印出来时,都是默认转换为双精度浮点数,也就是在在printf函数中,参数a是以32位入栈,但是打印取出时,却是按双精度取出64位,其中int的32位作为新的64位的低32位,高32位一般都为0。

 

在gdb中对程序进行反汇编:

ps:gcc中一般都有gdb,进入gcc,使用命令gcc –g test.c –o test,然后输入gdb test就可以进入gdb查看反汇编了。在gdb中,汇编指令格式默认是att的,使用命令set disassembly-flavor intel可以将反汇编格式设置成intel的,我将gdb中的汇编格式设置为Intel的,进入gdb后可以设置断点,可以单步执行,还可以将某个函数的汇编打印出来,从汇编中可以看到int确实是以32位入栈的。

 

ps:浮点数的表示方法


s为标志位,为1则浮点数为负,为0浮点数为正,exponent为幂位,后面的mantissa为有效位

 

下面再来看一个例子:

#include <stdio.h>

int main()

{

       __int64 b;

       b= 0x404B800000000000;

       int a ;

       a= 55;

       printf("%f\n%f\n%f\n",a,b,);

       printf("\n%f\n%f\n%f\n",b,a,);

       return0;

}

这里说明一下C语言里面参数的入栈和出栈顺序,C方式参数入栈顺序(从右至左)的好处就是可以动态变化参数个数。通过栈堆分析可知,自左向右的入栈方式,最前面的参数被压在栈底。除非知道参数个数,否则是无法通过栈指针的相对位移求得最左边的参数。这样就变成了左边参数的个数不确定,正好和动态参数个数的方向相反,如上面第一个printf函数,入栈顺序为b,a,出栈顺序为a、b,a为我定义的一个64位的int变量,为了更好的说明结果,我将55.0的浮点数的64位16进制表示赋给了b,在gcc中运行结果为:

0.000000

0.000000

 

55.000000

0.000000

在第一个printf中,数据一这样的顺序入栈:0x40B80000、0x0、0x37,出栈后变为0x0000000000000037、0x........40B80000,........一般为0所以结果就为0.000000、0.000000,(有时最后一个可能是乱码)。

 在这中间我也有很多不明白的地方,比如反汇编中,我找不到参数在printf中是怎么输出的,还有堆和栈的概念也不是很清晰,这次让我认识到自己的基础很不扎实,唉,小小叹息一下。

programming on the way


<think>嗯,用户遇到了CubeMX中'unterminated function-like macro invocation'的错误,需要解决这个问题。首先,我需要回忆一下这个错误通常是什么原因引起的。根据用户提供的引用信息,比如引用[3]提到的“unterminated argument list invoking macro”,这可能与宏调用时参数列表没有正确结束有关。也就是说,可能在代码中使用宏的时候,参数没有正确闭合,比如缺少右括号或者逗号。 接下来,我应该考虑CubeMX生成的代码中常见的宏使用场景,比如HAL库中的宏,或者用户自定义的宏。比如,用户可能在调用类似`__HAL_TIM_SET_COMPARE(&htim, TIM_CHANNEL_1, value)`这样的宏时,如果参数数量不对,或者括号不匹配,就会触发这个错误。 然后,我需要思考可能的解决方案。首先,检查宏调用的语法是否正确,参数数量是否匹配,括号是否成对。比如,用户可能在代码中少写了一个括号,导致宏没有被正确终止。其次,检查是否有嵌套宏调用导致的问题,可能需要拆分成行或者使用临时变量。另外,CubeMX生成的代码有时可能会因为版本问题或配置错误导致宏调用不正确,这时候需要检查配置或更新软件。 用户提供的引用[2]中提到关于min和宏的警告,这可能是因为在使用类似min或max的宏时参数不足,比如写成`min()`而没有参数。所以,在用户代码中如果有类似的宏使用,需要检查参数是否正确。此外,引用[1]提到的函数重复定义可能不是直接相关,但也需要注意是否有宏定义冲突的情况。 可能的解决步骤包括: 1. 检查报错位置附近的宏调用,确认参数数量和括号是否正确。 2. 检查是否有嵌套宏,尝试简化或拆分。 3. 确保CubeMX配置正确,重新生成代码测试。 4. 更新CubeMX和HAL库版本,避免已知的bug。 5. 检查包含的头文件,确认宏定义正确无误。 6. 如果问题依旧,可能需要查看编译器文档或社区讨论,寻找类似问题的解决方案。 同时,用户可能需要查看具体的错误信息指向的代码行,定位到具体的宏调用,比如在STM32的HAL库中,某些宏可能需要特定的参数类型或数量。例如,配置定时器的时候,如果参数顺序错误或缺少参数,就会导致这种错误。另外,代码中的注释或字符串内的特殊符号也可能意外干扰宏的解析,需要检查是否有拼写错误或未闭合的引号。 总结来说,解决这个问题的关键在于仔细检查宏调用的语法,确保所有参数正确且括号匹配,同时考虑CubeMX配置和库版本的影响。如果用户能提供具体的错误信息和相关代码片段,可以更准确地诊断问题所在。</think>### CubeMX中'unterminated function-like macro invocation'问题解决方案 #### 问题原因分析 该错误通常由以下原因导致: 1. **宏调用参数未正确闭合**:例如缺少右括号、逗号或参数数量不符,如`HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0` 缺少闭合括号[^3]。 2. **嵌套宏调用结构异常**:如`MAKE_CALLBACK(printf("test"))`未正确处理参数边界。 3. **CubeMX生成代码异常**:特定版本可能存在宏生成逻辑错误(如HAL库v1.27.1中部分定时器宏问题)[^2]。 #### 解决步骤 1. **定位错误位置** - 查看编译错误输出的具体行号,如: ```c main.c(45): error: unterminated function-like macro invocation ``` - 定位到类似代码段: ```c __HAL_TIM_SET_COMPARE(&htim, TIM_CHANNEL_1, 100 // 缺少闭合括号 ``` 2. **检查基础语法** - 补全参数闭合符号: ```c __HAL_TIM_SET_COMPARE(&htim, TIM_CHANNEL_1, 100); // 修正后 ``` - 检查参数数量匹配,如`HAL_ADC_Start(&hadc, 1)`应改为`HAL_ADC_Start(&hadc)`。 3. **处理复杂宏调用** - 避免层嵌套: ```c // 错误示例 SET_VALUE(MAX(a, b)) // 应改为 int temp = MAX(a, b); SET_VALUE(temp); ``` 4. **更新开发环境** - 升级CubeMX至最新版(当前最新v6.7.0) - 更新HAL库版本: ```shell Help > Manage Embedded Software Packages > 选择最新STM32xx HAL ``` 5. **检查特殊符号转义** - 处理含特殊字符的字符串: ```c printf("This is \"macro\" test"); // 正确转义引号 ``` #### 验证方法 1. 创建最小测试工程: ```c void MX_GPIO_Init(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 标准宏调用 } ``` 2. 逐步添功能模块,观察错误复现节点。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值