宏定义

本文介绍了几个用于结构体操作的宏,包括计算结构体内元素偏移量和通过成员指针获取结构体首地址的方法。此外,还展示了如何使用宏进行系统错误检测。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

几个有关于结构体的宏

检测系统错误的宏。

#include <stdio.h>
#include <stdlib.h>
#define handle_error(msg)   \
                do{perror(msg); exit(EXIT_FAILURE);}while(0)

//perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字
//符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno(这里的说法不
//准确,errno是一个宏,该宏返回左值) 的值来决定要输出的字符串。
//在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用"某
//些"函数出错时,该函数已经重新设置了errno的值。perror函数只是将你输入的一些信息和
//现在的errno所对应的错误一起输出。

//C  标准定义了两个值   EXIT_SUCCESS   和   EXIT_FAILURE,可以作为   exit()   
//       的参数,来分别指示是否为成功退出。
//exit(参数)传递给的是父进程,或者shell终端

#define FUNC  printf("所在文件%s所在行数%d.\n", __FILE__, __LINE__)
int main(void)
{   
    int fd = -1;
    int ret = close(fd);
    if(ret == -1)
    {
        handle_error("file error.\n");
    }
    return 0;
}

两个有关于内核的结构体的宏

/*
        linux内核里的两个宏:在驱动应用中很广泛。
        off_set_of(type, member)计算结构体内元素的偏移量
        containe_of(ptr, type, member),ptr是结构体里成员的指针,通过调用这个宏计算出结构体的首地址.包含两句代码(表达式),必须要加{}.
        这两个宏:内核双链表。
*/

//分析:        1、(type *)0指向结构体零地址
             2、((type *)0)->member得到了结构体某个成元变量名    \
             3、给这成员变量名,取地址(相对于零地址),此时&(((type *)0)->member)表示是指针类型 \
             4、强制类型转换成(long)。
             5.最后得到结构体的首地址
#define off_set_of(type, member)  ((long)&(((type *)0)->member))
//分析:1、得到结构体成员变量的类型 2、指针赋值(得到真实成员变量的地址值)
// 3、减去偏移量得到一个数字,该数字和结构体本身首地址在数值上一样
//4、最后强制类型转换为结构体指针类型
#define container_of(ptr, type, member)                     \
({typeof(((type *)0)->member) *_mptr = ptr;                 \
(type *)((char *)_mptr-off_set_of(type, member));})
#include <stdio.h>
struct da
{
        int a;
        short b;
        int c;
        double e;
};
struct data
{
        char a;
        short b;
        int c;              // 8
//      float d;            // 8
        double e;           // 8
        struct da s;    // 16
        char ch;
}s = {1, 3, 10, 3.14, 1.41};
int main(void)
{
        printf("sizeof(s) = %d.\n", sizeof(s));
        //结构体自身的首地址
        printf("&s = %p.\n", &s);
        struct da *p = container_of(&s.s.b, struct da, b);
        printf("p = %p.\n", p);
        printf("&s.s = %p.\n", &s.s);
        //计算结构体的某个元素的偏移量。
        int off = off_set_of(struct data, c);
        printf("off = %d.\n", off);     // off 4
        off = off_set_of(struct data, d);
        printf("off = %d.\n", off);         // off 8
        off = off_set_of(struct data, e);
        printf("off = %d.\n", off);         // off 16
        double *p_e = (double *)((char *)&s+off);
        printf("*p_e = %.2f.\n", *p_e);
        printf("&s = %p.\n", &s);
        //计算结构体的首地址。

        return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值