(void) (&_min1 == &_min2);

本文解析了Linux内核中泛型宏min的实现细节,特别是如何通过(void)(&_min1==&_min2)避免不同类型变量间的比较,有效防止编译警告。

偶然在<./linux/include/linux/kernel.h>里面看到下面这个宏定义:

 #define min(x, y) / ({ /

                                    typeof(x) _min1 = (x); /

                                     typeof(y) _min2 = (y); /

                                    (void) (&_min1 == &_min2); /

                                    _min1 < _min2 ? _min1 : _min2; /

                                 })

这就是一个泛型宏。使用了GCC的扩展支持命令typeof() 。一共四行代码,其他都很明了,唯独第三行让人有点摸不着头脑。我第一反应这是为了防止编译器优化代码结构而添加的语句。但是回头想了一下,没有想出理由来。也就没在意了。 今天一个很突然的机会才反应过来这么做的原因:为防止不同类型变量进行比较。

int main(int ac, char** av)

{

           char i = 100;

           long j = 1000;

           long k = min(i, j);

           return 0;

}

 编译上述代码时编译器会给出警告:comparison of distinct pointer types lacks a cast 如果去掉(void) (&_min1 == &_min2) 这行,再编译是不会给出警告的。 这群写内核人太TMD牛X了。 本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/shoui/archive/2010/01/10/5169225.aspx

那么为什么(void) (&_min1 == &_min2); 会使编译器报出警告呢?这就是指针的类型的问题:

比如:

int main ()
{

    int *p1;
    char *p2;

    int a = 10;
    char b = 20;

    p1 = &a;
    p2 = &b;

  
    p1 == p2;
    return 0;
}

 

 编译上述代码时编译器会给出警告:comparison of distinct pointer types lacks a cast 。“==”是比较的意思。也就是指针的类型不同是不能相互比较的。因为指针p1它指向含有4个字节连续的首地址,而指针p2 它指向含有1个字节的地址。

 

 

 

 

 

#include &quot;stm32f10x.h&quot; // Device header #include &quot;Delay.h&quot; #include &quot;Trace.h&quot; #include &quot;Motor.h&quot; #include &quot;PWM.h&quot; #include &quot;PID.h&quot; #define PWM_COMPARE_MIN 0 // 定义PWM比较值的上下限(0~900) #define PWM_COMPARE_MAX 450 int right_base_speed = 56; // 右轮基础速度(起码能动) int lift_base_speed = 70; // 左轮基础速度(起码能动) int value=0; int right_value =0; int left_value = 0; void Trace_task(void) { //0是亮灯检测到黑线,1是灭灯没检测到黑线 //Compare3控制右侧电机,Compare4控制左侧电机,跟据CCR3和CCR4的比较值来写Compare3和Compare4的值 //基准,最低56,70 if(X1==1&amp;&amp;X2==1&amp;&amp;X3==1&amp;&amp;(X4==0||X5==0)&amp;&amp;X6==1&amp;&amp;X7==1&amp;&amp;X8==1) //直走 { // PWM_SetCompare3(65); // PWM_SetCompare4(79); right_value=right_base_speed + pid_controller.Output;//控制右侧电机的转速 left_value=lift_base_speed - pid_controller.Output;//控制左侧电机的转速 } else if((X1==0 || X2==0 || X3==0) &amp;&amp;X6==1&amp;&amp;X7==1&amp;&amp;X8==1) //左拐 { if(X1==1&amp;&amp; (X2==0||X3==0))//中小拐 右83,左93 最低56,70 { // PWM_SetCompare3(105); // PWM_SetCompare4(70); right_value=right_base_speed + pid_controller.Output;//控制右侧电机的转速 left_value=lift_base_speed - pid_controller.Output;//控制左侧电机的转速 } if(X1==0)//大中拐 { // PWM_SetCompare3(115); // PWM_SetCompare4(70); right_value=right_base_speed + pid_controller.Output;//控制右侧电机的转速 left_value=lift_base_speed - pid_controller.Output;//控制左侧电机的转速 } } else if(X1==1 &amp;&amp; X2==1 &amp;&amp; X3==1 &amp;&amp;(X6==0||X7==0||X8==0)) //右拐 右83,左93 最低56,70 { if(X8==1&amp;&amp;(X6==0||X7==0))//中小拐 { // PWM_SetCompare3(56); // PWM_SetCompare4(105); right_value=right_base_speed + pid_controller.Output;//控制右侧电机的转速 left_value=lift_base_speed - pid_controller.Output;//控制左侧电机的转速 } if(X8==0)//大中拐 { // PWM_SetCompare3(56); // PWM_SetCompare4(125); right_value=right_base_speed + pid_controller.Output;//控制右侧电机的转速 left_value=lift_base_speed - pid_controller.Output;//控制左侧电机的转速 } } else if(X1==0&amp;&amp;X2==0&amp;&amp;X3==0&amp;&amp;X4==0&amp;&amp;X5==0&amp;&amp;X6==0&amp;&amp;X7==0&amp;&amp;X8==0) { right_value=0; left_value=0; } else if(X1==1&amp;&amp;X2==1&amp;&amp;X3==1&amp;&amp;X4==1&amp;&amp;X5==1&amp;&amp;X6==1&amp;&amp;X7==1&amp;&amp;X8==1) { right_value=0; left_value=0; } void limit_set_pwm_compare(int left_value, int right_value); } // 限速保护函数 uint16_t limit_pwm_compare(int value) { if (value &lt; PWM_COMPARE_MIN) { return PWM_COMPARE_MIN; } else if (value &gt; PWM_COMPARE_MAX) { return PWM_COMPARE_MAX; } else { return (uint16_t)value; } } void limit_set_pwm_compare(int rignt_value, int left_value) { uint16_t limit_left_pwm_compare = limit_pwm_compare(left_value); uint16_t limit_right_pwm_compare =limit_pwm_compare(right_value); // 使用PWM_SetCompare3和PWM_SetCompare4设置左右轮PWM比较值 PWM_SetCompare3(limit_right_pwm_compare); PWM_SetCompare4(limit_left_pwm_compare); } 这段代码可以起到限速的作用吗
最新发布
09-27
我们来**逐行分析你这段代码是否能起到限速作用**,并指出所有关键问题。 --- ## ❌ 结论先行: &gt; **这段代码不能正确起到限速保护的作用!** 虽然你写了限幅函数 `limit_pwm_compare` 和设置函数 `limit_set_pwm_compare`,但由于以下 **多个严重错误**,导致限速逻辑 **没有被执行或调用失败**。 --- ## 🔍 详细问题剖析 ### ✅ 1. 限幅函数本身写对了(这部分 OK) ```c uint16_t limit_pwm_compare(int value) { if (value &lt; PWM_COMPARE_MIN) { return PWM_COMPARE_MIN; } else if (value &gt; PWM_COMPARE_MAX) { return PWM_COMPARE_MAX; } else { return (uint16_t)value; } } ``` ✅ 这个函数是正确的:实现了对输入值的上下限裁剪(0~450),可以防止越界。 --- ### ❌ 2. 函数调用写成了&ldquo;声明&rdquo;而不是&ldquo;调用&rdquo;&mdash;&mdash;致命错误! 在 `Trace_task()` 最后你写了这一句: ```c void limit_set_pwm_compare(int left_value, int right_value); ``` ⚠️ 这不是调用函数!这是 **函数原型声明(function declaration)**,它只是告诉编译器&ldquo;有这么个函数&rdquo;,但 **不会执行任何操作!** 👉 正确的调用方式应该是: ```c limit_set_pwm_compare(left_value, right_value); // 没有 void,没有参数类型 ``` 你现在这样写,相当于什么都没做! --- ### ❌ 3. 参数名拼写错误:`rignt_value` 打错了! 看这个函数定义: ```c void limit_set_pwm_compare(int rignt_value, int left_value) { uint16_t limit_left_pwm_compare = limit_pwm_compare(left_value); uint16_t limit_right_pwm_compare = limit_pwm_compare(right_value); // &larr; 使用的是 right_value(全局变量) ... } ``` 注意: - 函数参数是 `int rignt_value`(少了一个 `h`,应该是 `right_value`) - 但在函数体内你用了 `right_value`(全局变量) - 而传进来的参数 `rignt_value` 根本没被使用! 这会导致: - 编译器可能报错或警告(未使用参数) - 实际使用的还是全局变量 `right_value`,但如果名字打错,可能导致不可预期行为 📌 必须改为: ```c void limit_set_pwm_compare(int right_value, int left_value) ``` --- ### ❌ 4. `limit_set_pwm_compare` 的参数顺序混乱 你在调用时意图是: ```c limit_set_pwm_compare(left_value, right_value); ``` 但函数定义是: ```c void limit_set_pwm_compare(int right_value, int left_value) ``` 这意味着你把左轮值当成了右轮,右轮当成了左轮 &mdash;&mdash; **左右电机接反了!** 应该统一顺序。建议:**先 left,后 right** 或 **先 right,后 left**,保持一致。 推荐修改为: ```c void limit_set_pwm_compare(int left_val, int right_val) { PWM_SetCompare4(limit_pwm_compare(left_val)); // 左轮 &rarr; CCR4 PWM_SetCompare3(limit_pwm_compare(right_val)); // 右轮 &rarr; CCR3 } ``` 然后调用: ```c limit_set_pwm_compare(left_value, right_value); ``` --- ### ✅ 5. 数据计算部分没问题(PID 加减合理) 你在各个分支中计算: ```c right_value = right_base_speed + pid_controller.Output; left_value = lift_base_speed - pid_controller.Output; ``` ✅ 这是典型的差速转向控制逻辑,合理。 但问题是:这些值 **没有经过限制就直接赋给全局变量**,如果 `pid_controller.Output` 很大(比如 &plusmn;200),那么 `left_value` 或 `right_value` 就可能变成负数或超过 450,超出 PWM 合法范围。 所以必须通过 `limit_pwm_compare` 裁剪后再输出! --- ### ❌ 6. 没有在每次循环都更新 PWM(潜在失控风险) 你只是在最后尝试&ldquo;声明&rdquo;了一下函数,并没有真正调用 `PWM_SetCompareX()` 来刷新输出。 即使前面算好了 `left_value` 和 `right_value`,如果不及时写入定时器比较寄存器,电机速度就不会改变! --- ## ✅ 正确改法(完整修正版) ```c #include &quot;stm32f10x.h&quot; #include &quot;Delay.h&quot; #include &quot;Trace.h&quot; #include &quot;Motor.h&quot; #include &quot;PWM.h&quot; #include &quot;PID.h&quot; #define PWM_COMPARE_MIN 0 #define PWM_COMPARE_MAX 450 int right_base_speed = 56; int left_base_speed = 70; // 注意:原代码写成 lift_base_speed &rarr; 应该是 left int left_value = 0; int right_value = 0; // 限幅函数(正确) uint16_t limit_pwm_compare(int value) { if (value &lt; PWM_COMPARE_MIN) { return PWM_COMPARE_MIN; } else if (value &gt; PWM_COMPARE_MAX) { return PWM_COMPARE_MAX; } else { return (uint16_t)value; } } // 设置电机速度并自动限幅(修正参数名和顺序) void limit_set_pwm_compare(int left_val, int right_val) { uint16_t left_limited = limit_pwm_compare(left_val); uint16_t right_limited = limit_pwm_compare(right_val); PWM_SetCompare4(left_limited); // 左轮 &rarr; CCR4 PWM_SetCompare3(right_limited); // 右轮 &rarr; CCR3 } void Trace_task(void) { // 清除旧值 left_value = 0; right_value = 0; // 根据巡线传感器状态决定目标速度 if (X1==1 &amp;&amp; X2==1 &amp;&amp; X3==1 &amp;&amp; (X4==0||X5==0) &amp;&amp; X6==1 &amp;&amp; X7==1 &amp;&amp; X8==1) { // 直走 left_value = left_base_speed - pid_controller.Output; right_value = right_base_speed + pid_controller.Output; } else if ((X1==0 || X2==0 || X3==0) &amp;&amp; X6==1 &amp;&amp; X7==1 &amp;&amp; X8==1) { // 左拐 left_value = left_base_speed - pid_controller.Output; right_value = right_base_speed + pid_controller.Output; } else if (X1==1 &amp;&amp; X2==1 &amp;&amp; X3==1 &amp;&amp; (X6==0||X7==0||X8==0)) { // 右拐 left_value = left_base_speed - pid_controller.Output; right_value = right_base_speed + pid_controller.Output; } else if ((X1==0 &amp;&amp; X2==0 &amp;&amp; X3==0 &amp;&amp; X4==0 &amp;&amp; X5==0 &amp;&amp; X6==0 &amp;&amp; X7==0 &amp;&amp; X8==0) || (X1==1 &amp;&amp; X2==1 &amp;&amp; X3==1 &amp;&amp; X4==1 &amp;&amp; X5==1 &amp;&amp; X6==1 &amp;&amp; X7==1 &amp;&amp; X8==1)) { // 全黑或全白 &rarr; 停止 left_value = 0; right_value = 0; } else { // 其他异常情况也停止 left_value = 0; right_value = 0; } // ✅ 真正调用限幅并设置 PWM(这才是有效执行) limit_set_pwm_compare(left_value, right_value); } ``` --- ## ✅ 改进点总结 | 问题 | 修复方式 | |------|---------| | 把函数调用写成声明 | 改为 `limit_set_pwm_compare(left_value, right_value);` | | 参数名拼写错误 `rignt_value` | 改为 `right_value` | | 参数顺序混乱 | 统一为 `(left, right)` 或 `(right, left)`,建议 `(left, right)` | | 全局变量命名错误 `lift_base_speed` | 改为 `left_base_speed` 更清晰 | | 没有实际调用限幅设置 | 在 `Trace_task` 结尾添加真实调用 | --- ## ✅ 补充建议 - 可以进一步将 `limit_pwm_compare` 写成宏(性能更高): ```c #define LIMIT(x, min, max) (((x) &lt; (min)) ? (min) : ((x) &gt; (max)) ? (max) : (x)) ``` - 使用 `static inline` 提高效率: ```c static inline uint16_t limit_pwm_compare(int v) { ... } ``` --- ##
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值