windows驱动编程学习(二)基础知识回顾之指针

勇哥注:

指针练习好了,能解决90%的驱动开发时遇到的各种问题。



#include<stdio.h>
typedef void(*p_fun)(int i, int j);
struct st {
    int i;
    int j;
    int b;
    p_fun p_fun1;
};

void fun(int i, int j) {
    printf("fun%d %d\n", i, j);
}

int main()
{
    struct st st_ = { 0 };
    st_.i = 1;
    st_.j = 2;
    st_.p_fun1 = fun;
    st_.p_fun1(1, 2);     //fun1 2
    printf("%p %p\n", st_.p_fun1, &st_.p_fun1);    //00007FF668281334   000000496FF2F5A8

    struct st* pst_;
    pst_ = &st_;
    printf("%d %d\n", st_.i, st_.j);      //1  2

    int* p_int = (int*)pst_;
    printf("+0 %d %p\n", *p_int, p_int);  //   1   0000001B7CB2F4F8
    //*p_int=1;
    p_int += 1;
    printf("+1 %d %p\n", *p_int, p_int);  //+1  2   0000001B7CB2F4FC
    //*p_int=2;
    
    p_int += 1;
    *p_int = 3;
    printf("+1 %d %p\n", *p_int, p_int);  //+1   3  0000001B7CB2F500
 
    p_int += 1;
    printf("+1 %d %p\n", *p_int, p_int);   //+1   0   0000001B7CB2F504

    p_int += 1;
    printf("+1 %p %p %p\n", *p_int, p_int, *(long long int*)p_int);   //+1 0000000068281334 000000496FF2F5A8 00007FF668281334

   
    p_fun p =(p_fun)(*(long long int*)p_int);
    printf("%p\n",p);           //00007FF65AF91334
   
    p(1, 2);                  //fun1 2

    (*(p_fun*)p_int)(2, 3);   //fun2 3

    printf("%lld\n", sizeof(struct st));    //24

    return 0;
  
}


结果:

image.png


勇哥解释一下:

(1)struct st st_ = { 0 };

这个是结构体的初始化,也称为聚合初始化或列表初始化。

i,j,b初始化为int的缺省0,p_fun1实始化为nullptr,也就是指向地址为0的指针。


(2)如果结构体的指针不赋值会怎么样呢

就像下面这样注释掉指针的值。

    struct st st_ = { 0 };
    st_.i = 1;
    st_.j = 2;
    //st_.p_fun1 = fun;
    st_.p_fun1(1, 2);
    printf("%p %p\n", st_.p_fun1, &st_.p_fun1);

这样的话,你会使用指向零的指针,根据编译器不同报的错误不同。

对于vs2022会报下面的错误。

image.png

对于macos下的c++编译器来说,报的是:

segmentation fault    段错误。

这种错误在内核里经常发生。


(3)代码:printf("%p %p\n", st_.p_fun1, &st_.p_fun1);

%p是格式符,表示 输出指针类型,%d就是输出整数类型

&是地址符。

st_.p_fun1输出的是st_.p_fun1指针内容(即fun函数的地址),&st_.p_fun1输出的是指针变量st_.p_fun1的地址(任何变量都有自己的地址,包括简单类型变量、数据变量、结构体变量)


(4)%d是输出整数类型

    struct st* pst_;
    pst_ = &st_;
    printf("%d %d\n", st_.i, st_.j);

结果是: 1  2


(5) 下面代码中,故意把pst_强行转为int*

然后用地址+1的方式,想取到st结构体的第4个元素。

这里值的注意的是,为什么需要+1四次才可以取到第4个元素。

原因是st的这第4个元素是函数指针,它占8个字节。而前面3个元素都是int,只占4个字节。

指针+1就等于按4个字节来向前移动。

 int* p_int = (int*)pst_;
 printf("+0 %d %p\n", *p_int, p_int);  //   1   0000001B7CB2F4F8


 p_int += 1;
 printf("+1 %d %p\n", *p_int, p_int);  //+1  2   0000001B7CB2F4FC
 
 p_int += 1;
 *p_int = 3;
 printf("+1 %d %p\n", *p_int, p_int);  //+1   3  0000001B7CB2F500
 
 p_int += 1;
 printf("+1 %d %p\n", *p_int, p_int);   //+1   0   0000001B7CB2F504

 p_int += 1;
 printf("+1 %p %p %p\n", *p_int, p_int, *(long long int*)p_int);   //+1 0000000068281334 000000496FF2F5A8 00007FF668281334


long long int*  这个是标准C定的。就是64位int.

如果不转64位,00007FF668281334就会显示为0000000068281334,即精度丢失了32位。


(6)printf("%lld\n", sizeof(struct st));    

为啥结果是24,而不是4+4+4+8=20字节?

原因是结构体的大小并不是按所有元素数据类型占的字节的总数这么算的。

必须要做字节边界对齐,这样内存读写效率才高。

所以结果是24,而不是20。




本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2024-07-24 13:46:40 编辑

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864