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

本文解析了Linux内核中一个复杂的min宏定义,该宏通过GCC扩展命令typeof()实现泛型最小值比较功能,并解释了其中(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了。

#include &lt;reg52.h&gt; #include &lt;Delay.h&gt; //小车轮胎 sbit IN1=P1^0; //左轮 请进 sbit IN2=P1^1; //左轮 后退 sbit IN3=P1^2; //右轮 前进 sbit IN4=P1^3; //右轮 后退 sbit ENA=P1^4; //左使能端1 sbit ENA1=P1^5; //右使能端2 //传感器检测 sbit accept_left=P2^0; //左侧检测 sbit accept_far_left=P2^1; //极左边检测 sbit accept_right=P2^2; //右侧检测 sbit accept_far_right=P2^3; //极右侧检测 unsigned char num1; unsigned int Count_ENA,Count_ENA1,count10us,countsete=65534; //检测输入 void stop() //全部停止 { Count_ENA=80; Count_ENA1=80; //可以适当调节减少误差 IN1=0; IN2=0; IN3=0; IN4=0; Delay100us(1); } void min_left() //小转左边检测 { Count_ENA=60; Count_ENA1=60; IN1=1; IN2=0; IN3=0; IN4=0; } void min_right() //小转右边检测 { Count_ENA=60; Count_ENA1=60; IN1=0; IN2=0; IN3=1; IN4=0; } void left() //大转左边检测 { Count_ENA=70; Count_ENA1=70; IN1=0; IN2=1; IN3=1; IN4=0; } void right() //大转右边检测 { Count_ENA=70; Count_ENA1=70; IN1=1; IN2=0; IN3=0; IN4=1; } void advance() //前进检测 { Count_ENA=80; Count_ENA1=80; IN1=1; IN2=0; IN3=1; IN4=0; Delay100us(1); } void retreat() //后退检测 { Count_ENA=65; Count_ENA1=65; IN1=0; IN2=1; IN3=0; IN4=1; Delay100us(1); } unsigned char test_trolley(unsigned char testnum) //寻迹判断 { if(count10us&gt;=5) { if((accept_left==0) &amp;&amp; (accept_far_left==0) &amp;&amp;(accept_right==0)&amp;&amp;(accept_far_right==0)) //全部为零 { testnum=3; } else if((accept_left==0) &amp;&amp; (accept_far_left==0) &amp;&amp;(accept_right==0)&amp;&amp;(accept_far_right==1)) { testnum=6; } else if((accept_left==0) &amp;&amp; (accept_far_left==0) &amp;&amp;(accept_right==1)&amp;&amp;(accept_far_right==0)) { testnum=6; } else if((accept_left==0) &amp;&amp; (accept_far_left==0) &amp;&amp;(accept_right==1)&amp;&amp;(accept_far_right==1)) { testnum=2; } else if((accept_left==0) &amp;&amp; (accept_far_left==1) &amp;&amp;(accept_right==0)&amp;&amp;(accept_far_right==0)) { testnum=7; } else if((accept_left==0) &amp;&amp; (accept_far_left==1) &amp;&amp;(accept_right==0)&amp;&amp;(accept_far_right==1)) { testnum=7; } else if((accept_left==0) &amp;&amp; (accept_far_left==1) &amp;&amp;(accept_right==1)&amp;&amp;(accept_far_right==0)) { testnum=3; } else if((accept_left==0) &amp;&amp; (accept_far_left==1) &amp;&amp;(accept_right==1)&amp;&amp;(accept_far_right==1)) { testnum=2; } else if((accept_left==1) &amp;&amp; (accept_far_left==0) &amp;&amp;(accept_right==0)&amp;&amp;(accept_far_right==0)) { testnum=7; } else if((accept_left==1) &amp;&amp; (accept_far_left==0) &amp;&amp;(accept_right==0)&amp;&amp;(accept_far_right==1)) { testnum=3; } else if((accept_left==1) &amp;&amp; (accept_far_left==0) &amp;&amp;(accept_right==1)&amp;&amp;(accept_far_right==0)) { testnum=6; } else if((accept_left==1) &amp;&amp; (accept_far_left==0) &amp;&amp;(accept_right==1)&amp;&amp;(accept_far_right==1)) { testnum=2; } else if((accept_left==1) &amp;&amp; (accept_far_left==1) &amp;&amp;(accept_right==0)&amp;&amp;(accept_far_right==0)) { testnum=1; else if((accept_left==1) &amp;&amp; (accept_far_left==1) &amp;&amp;(accept_right==0)&amp;&amp;(accept_far_right==1)) { testnum=1; } else if((accept_left==1) &amp;&amp; (accept_far_left==1) &amp;&amp;(accept_right==1)&amp;&amp;(accept_far_right==0)) { testnum=1; } else if((accept_left==1) &amp;&amp; (accept_far_left==1) &amp;&amp;(accept_right==1)&amp;&amp;(accept_far_right==1)) { testnum=3; } else { advance(); } count10us=0; } return testnum; } unsigned char select(unsigned char num2) { num1=test_trolley(num1); switch(num1) { case 1:left();break; //左转 case 2:right();break; //右转 case 3:advance();break;//前进 case 4:retreat();break;//后退 case 5:stop(); break; //停止 case 6:min_left(); break; //小左转检测 case 7:min_right();break; //小右转检测 } return num2; } void Timer0Init(void) //1毫秒@11.0592MHz { TMOD &amp;= 0xF0; //设置定时器模式 TL0 = 0x66; //设置定时初值 TH0 = 0xFC; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0=1; PT0=0; EA=1; } void timer0_routine() interrupt 1 //定时器里面在加一个变量分别用来表示ENA1和ENA2 { static unsigned int j,y,countnum; TL0 = 0x66; //设置定时初值 TH0 = 0xFC; //设置定时初值 countnum++; countsete++; if(countnum&gt;=2) //小车靠Pid误差运行 误差越大小车抖动的越快 { j++; y++; if(j&gt;=Count_ENA) {ENA=1;} else {ENA=0;} if(y&gt;=Count_ENA1) {ENA1=1;} else {ENA1=0;} if(j==100) { j=0; } if(y==100) { y=0; } countnum=0; } if(countsete&gt;=65535) { countsete=65525; count10us++; } }
最新发布
12-07
### 代码问题排查 #### 传感器检测部分 传感器检测代码可能存在的问题包括传感器数据读取错误、数据处理异常等。例如,若传感器返回的数据超出预期范围,可能是传感器故障或者代码中数据读取逻辑有误。 ```c // 示例:超声波传感器距离读取代码 #include &lt;reg51.h&gt; sbit Trig = P1^0; sbit Echo = P1^1; unsigned int get_distance() { unsigned int time; Trig = 1; delay_us(10); // 假设delay_us是一个延时函数 Trig = 0; while(Echo == 0); // 等待高电平 TR0 = 1; // 启动定时器 while(Echo == 1); TR0 = 0; // 停止定时器 time = TH0 * 256 + TL0; // 读取定时器值 TH0 = 0; TL0 = 0; return time * 0.017; // 计算距离 } ``` 排查时,可使用调试工具(如示波器)观察传感器引脚的电平变化,检查定时器是否正常工作,确保数据读取的准确性。 #### 电机控制部分 电机控制代码可能出现电机不转动、转动方向错误等问题。这可能是由于引脚配置错误、PWM信号输出异常等原因导致。 ```c // 示例:电机PWM控制代码 #include &lt;reg51.h&gt; sbit Motor1_PWM = P2^0; sbit Motor1_DIR = P2^1; void motor_control(unsigned char speed, bit direction) { Motor1_DIR = direction; // 假设使用定时器实现PWM if(speed &gt; 0) { // 设置定时器初值以实现不同占空比 TH0 = 0xFF - speed; TL0 = 0xFF - speed; TR0 = 1; } else { TR0 = 0; Motor1_PWM = 0; } } ``` 排查时,可使用万用表测量电机引脚的电压,检查PWM信号的占空比是否符合预期。 #### 寻迹判断部分 寻迹判断代码可能出现寻迹不准确、误判等问题。这可能是由于传感器阈值设置不合理、判断逻辑有误等原因导致。 ```c // 示例:寻迹传感器判断代码 #include &lt;reg51.h&gt; sbit Track_Sensor1 = P3^0; sbit Track_Sensor2 = P3^1; bit track_status() { if(Track_Sensor1 == 0 &amp;&amp; Track_Sensor2 == 0) { return 0; // 未检测到黑线 } else { return 1; // 检测到黑线 } } ``` 排查时,可使用不同颜色的测试板测试传感器的响应,调整阈值以提高寻迹的准确性。 ### 代码优化 #### 模块化设计 将不同功能的代码封装成独立的函数,提高代码的可读性和可维护性。例如,将传感器检测、电机控制、寻迹判断等功能分别封装成函数。 ```c // 模块化示例 #include &lt;reg51.h&gt; // 传感器检测函数 unsigned int get_sensor_data(); // 电机控制函数 void motor_control(unsigned char speed, bit direction); // 寻迹判断函数 bit track_status(); void main() { unsigned int sensor_data; bit track_result; while(1) { sensor_data = get_sensor_data(); track_result = track_status(); if(track_result) { motor_control(50, 1); // 示例:检测到黑线,电机转动 } else { motor_control(0, 0); // 未检测到黑线,电机停止 } } } ``` #### 减少资源占用 优化代码逻辑,减少不必要的循环和延时,提高系统的响应速度。例如,使用中断方式处理传感器数据,避免长时间的轮询。 ```c // 中断方式处理传感器数据示例 #include &lt;reg51.h&gt; sbit Sensor_Int = P3^2; void sensor_interrupt() interrupt 0 { // 处理传感器数据 } void main() { IT0 = 1; // 下降沿触发中断 EX0 = 1; // 使能外部中断0 EA = 1; // 全局中断使能 while(1) { // 主循环其他任务 } } ``` ### 技术支持 可通过查阅C51单片机的官方文档、相关技术论坛(如51黑电子论坛)获取更多技术支持。还可以参考开源项目的代码,学习他人的经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值