从kernel和其他opensource 扒出来的常见的宏

本文介绍了一种避免宏参数多次计算的方法,并给出了GCC扩展中确保参数仅计算一次的宏定义实例。此外,还列举了Linux内核中常用的高效宏定义,如MAX_CHECK、offsetof和container_of等。
http://www.xxlinux.com/linux/article/development/soft/20070816/9335.html

比如比较两个数的大小 : 一般我们都习惯了这样写:
#define MAX(a,b) (((a)>(b))?(a)b)) //实际上宏参数计算两次tyLLinux联盟
可是宏是有副作用的, 比如下面这个例子: MAX(a++,b) 又如何呢?
所以kernel里面的gcc扩展提供了很好的办法:tyLLinux联盟
 

#define MAX_CHECK(x,y)     / //宏参数仅仅计算一次tyLLinux联盟
tyLLinux联盟
({                /tyLLinux联盟
    typeof(x) __x = (x);    /tyLLinux联盟
    typeof(y) __y = (y);    /tyLLinux联盟
    (void) (&__x == &__y);    /tyLLinux联盟
    (__x>__y) ?__x:__y    ;/tyLLinux联盟
})注意上面的是语句表达式(就是 用() 括起来) , 当if(MAX_CHECK(10,20) ) 是没有副作用的。 typeof 是个宏, 取出变量的类型tyLLinux联盟

当然上面的宏 按照kernel里面的写法也可以写成这样:

#define MAX_CHECK2(x,y)     /tyLLinux联盟
do{                /tyLLinux联盟
    typeof(x) __x = (x);    /tyLLinux联盟
    typeof(y) __y = (y);    /tyLLinux联盟
    (void) (&__x == &__y);    /tyLLinux联盟
    (__x>__y) ?__x:__y    ;/tyLLinux联盟
}while(0)
//注意可没有;但是用法就不一样了,语句表达返回的是个值 , 但是 这点用 do {} while(0) 格式就不幸了。 tyLLinux联盟
tyLLinux联盟

比如 你可以这样 max = MAX_CHECK(a,b);tyLLinux联盟
但是这样就错了: max = MAX_CHECK2(a,b) ; 编译就出错了。 tyLLinux联盟
但是如果 一行里面直接写 MAX_CHECK2(a,b) 肯定就没有问题了。

---

下面是就是聪kernel里面扒出来的:

 

tyLLinux联盟
#define ARRAY_SIZE(X) ((sizeof((X)))/(sizeof((X)[0])))tyLLinux联盟
#define ALIGN(x,a)         (((x)+(a)-1) & (~((a)-1)))tyLLinux联盟
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))tyLLinux联盟
tyLLinux联盟
#define abs(x) ({                    /tyLLinux联盟
        int __x = (x);                /tyLLinux联盟
        (__x < 0) ? -__x : __x;        /tyLLinux联盟
    })tyLLinux联盟
    tyLLinux联盟
tyLLinux联盟
//太有用的宏了, 一定要掌握tyLLinux联盟
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)tyLLinux联盟

//也非常有用

/**tyLLinux联盟
 * container_of - cast a member of a structure out to the containing structuretyLLinux联盟
 * @ptr:    the pointer to the member.tyLLinux联盟
 * @type:    the type of the container struct this is embedded in.tyLLinux联盟
 * @member:    the name of the member within the struct.tyLLinux联盟
 *tyLLinux联盟
 */
tyLLinux联盟
#define container_of(ptr, type, member) ({            /tyLLinux联盟
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    /tyLLinux联盟
        (type *)( (char *)__mptr - offsetof(type,member) );})tyLLinux联盟
        tyLLinux联盟
        tyLLinux联盟
//#define container_of(ptr,type,member)tyLLinux联盟
tyLLinux联盟
//({                                                            /tyLLinux联盟
tyLLinux联盟
//    const typeof(((type *)0)->member) *__mptr = (ptr);    / //仅仅计算一次tyLLinux联盟
tyLLinux联盟
//    (type *)((char *)__mptr - offsetof(type,member)) ;        /tyLLinux联盟
tyLLinux联盟
//})tyLLinux联盟
tyLLinux联盟
    tyLLinux联盟
tyLLinux联盟
tyLLinux联盟
/**tyLLinux联盟
 * list_entry - get the struct for this entrytyLLinux联盟
 * @ptr:    the &struct list_head pointer.tyLLinux联盟
 * @type:    the type of the struct this is embedded in.tyLLinux联盟
 * @member:    the name of the list_struct within the struct.tyLLinux联盟
 */
tyLLinux联盟
#define list_entry(ptr, type, member) /tyLLinux联盟
    container_of(ptr, type, member)tyLLinux联盟
tyLLinux联盟
//#define abs(x)    ((x) > 0)?(x):(-(x))tyLLinux联盟
tyLLinux联盟
tyLLinux联盟
/*tyLLinux联盟
 * ..and if you can't take the stricttyLLinux联盟
 * types, you can specify one yourself.tyLLinux联盟
 *tyLLinux联盟
 * Or not use min/max at all, of course.tyLLinux联盟
 */
tyLLinux联盟
#define MIN_T(type,x,y) /tyLLinux联盟
    ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })tyLLinux联盟
#define MAX_T(type,x,y) /tyLLinux联盟
    ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })tyLLinux联盟
tyLLinux联盟
#define MAX(x,y)    ( (x)>(y)?(x):(y) )tyLLinux联盟
#define MAX_CHECK(x,y)     /tyLLinux联盟
({                /tyLLinux联盟
    typeof(x) __x = (x);    /tyLLinux联盟
    typeof(y) __y = (y);    /tyLLinux联盟
    (void) (&__x == &__y);    /tyLLinux联盟
    (__x>__y) ?__x:__y    ;/tyLLinux联盟
})






({ /tyLLinux联盟

typeof(x) __x = (x); /tyLLinux联盟

typeof(y) __y = (y); /tyLLinux联盟

(void) (&__x == &__y); /tyLLinux联盟

(__x>__y) ?__x:__y ;/tyLLinux联盟

}) tyLLinux联盟

其中(void) (&__x == &__y);的目的是什么? tyLLinux联盟

tyLLinux联盟

检查两个变量的类型是否相同,如果不相同,编译的时候会有警告。tyLLinux联盟

比如 tyLLinux联盟

int a=8;tyLLinux联盟

flat b = 1.5 ; tyLLinux联盟
<think> 我们正在处理一个设备树源文件(.dtsi)中的语法错误。文件路径是: /work/0003/workspace/Personal_Debug_Release/pro/code/source/vnd/kernel_platform/msm-kernel/../../vendor/qcom/opensource/display-devicetree/./display/dsi-panel-AA610-P-3-A0034-dsc-vid.dtsi 错误发生在第59.5行第6行?这个行号描述有点模糊。通常,行号是整数。这里“59.5”可能是编辑器中显示的一个位置(比如第59行中间),但实际在文本文件中,我们只能按行号来处理。另外,第6行也被提到。不过,用户主要关注的是第59.5行附近(可能是第59行或60行)第6行。 由于我们无法直接查看文件,需要根据常见的设备树语法错误用户提供的上下文来推测。 设备树语法错误常见原因: 1. 缺少分号(;)或逗号(,) 2. 括号不匹配(花括号{},方括号[]) 3. 属性名拼写错误 4. 节点名称或标签错误 5. 引用的节点路径错误 6. 使用了未定义的 用户提供的引用中,有两条可能与设备树相关: 引用[2]:提到了dts中没有某个属性,以及soc/qcom/mpm-of.c中的compatible属性。 引用[4]:展示了一个设备树片断,其中包含路由配置(&route_dsi0&route_dsi1)。 但是,我们的具体错误在dsi-panel-AA610-P-3-A0034-dsc-vid.dtsi文件中。这个文件是描述一个DSI显示面板的设备树节点。 由于用户提到第59.5行第6行,我们推测可能是两个位置有错误。 首先,我们需要明确错误的具体行号。由于“59.5”不是整数行号,可能是用户从编辑器看到的(比如第59行有错误,错误在中间位置),但实际我们只需要检查第59行第60行。另外,第6行可能是另一个错误位置。 常见的解决步骤: 1. 打开文件,定位到指定行号(第6行第59行附近)。 2. 检查这些行的语法,特别是上述常见错误。 3. 检查上下文,因为有时错误可能由前面行引起(比如缺少分号导致后面解析出错)。 由于我们无法直接查看文件,只能提供一般性建议: 1. 对于第6行: - 检查是否缺少分号(;)或逗号(,)。 - 检查括号是否匹配(比如开了大括号{却没有闭合})。 - 检查属性名是否正确(比如compatible,reg等)。 2. 对于第59行附近(可能是59行或60行): - 同样检查分号、逗号括号。 - 特别注意,设备树节点中,每个属性赋值后面都要有分号,除非是同一个花括号内的最后一个属性(但实际上每个属性赋值都需要分号)。 - 检查字符串是否正确使用双引号,以及是否有多余的字符。 另外,用户提到“第59.5 - 6行”,这个描述可能是指从第59行到第60行(因为59.5可能表示59行60行之间)。因此,我们需要检查第59行第60行。 假设错误在第59行第60行,常见的错误可能是: - 第59行末尾缺少分号,导致第60行解析出错。 - 第59行或第60行有拼写错误。 举例: ```dts /* 错误示例:第59行末尾缺少分号 */ qcom,mdss-dsi-panel-width = <1080> qcom,mdss-dsi-panel-height = <2400>; ``` 这里第一行缺少分号,应该为: ```dts qcom,mdss-dsi-panel-width = <1080>; ``` 另外,注意属性值中的尖括号<>是用于表示数值的,确保里面的数字格式正确。 如果第6行也有错误,那么可能是文件开头的节点定义有问题。例如: ```dts /* 第6行错误示例:节点名称后缺少空格或冒号 */ panel@0 { compatible = "dsi-panel"; ... }; ``` 正确的节点定义是:`标签: 节点名@地址 { ... }` 或 `节点名@地址 { ... }` 建议用户: 1. 仔细检查指定行号的语法。 2. 使用设备树编译器(dtc)进行编译,它会指出错误的具体位置原因。 命令示例(在Linux环境下): ```bash dtc -I dts -O dtb -o /dev/null dsi-panel-AA610-P-3-A0034-dsc-vid.dtsi ``` 运行该命令后,dtc会输出错误信息,包括错误行号具体原因。 根据用户提供的引用[2]中,有提到dts中缺少某个属性,所以也要检查相关属性是否定义正确。 由于错误信息不完整,我们只能提供这些一般性建议。 相关问题: 1. 设备树语法错误常见原因有哪些? 2. 如何使用dtc编译检查设备树文件? 3. 在设备树中定义DSI面板节点时需要注意哪些关键属性? 以上建议问题基于常见情况,具体错误需要用户查看文件内容。 </think> ### 解决 DTSI 文件语法错误的方法 针对文件 `dsi-panel-AA610-P-3-A0034-dsc-vid.dtsi` 第 59-60 行的语法错误(实际可能是 59-60 行,因行号 59.5 可能是编辑器的中间位置标记),以下是系统性的解决方案: #### 1. **定位并检查错误区域** ```dts // 示例:第 59-60 行附近的典型错误结构 qcom,mdss-dsi-panel-timings = [ 00 1A 06 06 0A 03 /* 第 59 行 */ 04 a0 00 /* 第 60 行 - 注意可能的非法字符或格式 */ ]; ``` **常见错误类型**: - 缺少分号 `;` 或逗号 `,` - 十六进制值包含非法字符(如 `a0` 未大写为 `A0`) - 括号/方括号未闭合(如 `[...]` 未闭合) - 节点引用格式错误(如 `&label` 未定义) #### 2. **验证属性语法** ```dts /* 正确格式示例 */ qcom,mdss-dsi-panel-timings = [ 00 1A 06 06 0A 03 // 十六进制必须全大写 04 A0 00 // 修正大小写 ]; // 方括号闭合 ``` - **关键规则**: - 十六进制值必须全大写(`A0` 合法,`a0` 非法) - 数组末尾需闭合方括号 `]` - 属性结尾需分号 `;`(除非是多行数组) #### 3. **检查节点标签引用** 引用[4] 中提到 `&route_dsi0` 这类标签路由: ```dts &dsi_panel { // 引用必须匹配已定义的节点标签 status = "okay"; qcom,mdss-dsi-panel = <&your_panel_label>; // & 后标签需存在 }; ``` - 确认 `dsi-panel-AA610...` 节点是否正确定义标签(如 `label: dsi_panel_AA610 { ... }`) #### 4. **使用 DTC 编译验证** 运行设备树编译器检测具体错误: ```bash dtc -I dts -O dtb -o /dev/null dsi-panel-AA610-P-3-A0034-dsc-vid.dtsi ``` - 错误输出示例: ``` Error: dsi-panel-AA610...dtsi:59.5: syntax error FATAL ERROR: Unable to parse input tree ``` #### 5. **交叉参考硬件配置** 引用[3][5] 提到 MIPI-DSI 协议要求: - 检查时序参数是否匹配面板规格书(如 `qcom,mdss-dsi-*` 系列属性) - 确认 D-PHY 时钟配置(引用[5])是否冲突 #### 修复后验证 ```dts // 修复后的示例(假设错误是十六进制大小写) qcom,mdss-dsi-panel-timings = [ 00 1A 06 06 0A 03 04 A0 00 // 修正 a0 → A0 ]; // 确保闭合 ``` > **注意**:若错误涉及桥接逻辑(引用[1][4]),需同步检查 DSI 路由配置(如 `&route_dsi0` 状态)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值