C语言Warning:assignment to ‘int‘ from ‘int*‘ makes integer from pointer without a cast引发的思考

目录

0 前言

1 这个警告是什么意思?

2 深入思考

2.1 引起问题的错误理解    

2.2 警告出现的原因与解决方案探索

2.3 进一步思考

3 总结与唠嗑环节


0 前言

    适逢研0假期,研究生导师暂未安排任务,鄙人自学之余,想起本科恩师叮咛:“嵌入式的能力不能丢。”,遂将嵌入式C语言也纳入自学范围之中,重新打基础。一日见网课老师程序示例,如下图所示。

     于是临时起兴,在VSCode中进行指针的初级实验,敲入如下代码

#include <stdio.h>

int main()
{
    int a = 0x12345678;
    int *p;

    *p = (int *) &a;
    printf("the *p is %x.\n", *p);
    printf("the p is %x.\n", p);

    p = &a;
    printf("the *p is %x.\n", *p);
    printf("the p is %x.\n", p);

}

    自信满满点击运行,结果喜提Warning:assignment to 'int' from 'int*' makes integer from pointer without a cast。输出结果则如下所示。

the *p is 5ffe94.
the p is 1b5d90.
the *p is 12345678.
the p is 5ffe94.

    自行琢磨一会儿自觉没什么问题(鄙人粗陋基础可见一斑),遂请教高人,得启发,将此次所得进行记录。

1 这个警告是什么意思?

    意思是我们将int类型的值赋给了一个int*类型的变量。

    按图索骥,重新回看代码——不对啊,我明明加了强制类型转换不是吗?而且视频里老师也是这么写的,也没有报Warning呀?

2 深入思考

2.1 引起问题的错误理解    

    对比老师的示例代码,发现老师是在初始化指针变量的时候对其进行了赋值,于是我修改了代码,尝试也在初始化指针变量的时候对其进行赋值,如下所示。

int main()
{
    int a = 0x12345678;
    int *p = &a;

    printf("the *p is %x.\n", *p);
    printf("the p is %x.\n", p);

    p = &a;
    printf("the *p is %x.\n", *p);
    printf("the p is %x.\n", p);

}

    再看输出结果,很好,符合预期。

the *p is 12345678.
the p is 5ffe94.
the *p is 12345678.
the p is 5ffe94.

    结合高人所述,当我们初始化指针变量时写的这句int *p实际上是定义了一个int*类型的变量p,更好理解就是(int*) p而不是int (*p)。

    在初始化时也应该认为是(int*) p = &a,而不是int (*p = &a)。

    即初始化的这一句,

int *p = &a;

    其效果等价于我们写了以下这两句。

int *p;
p = &a;

2.2 警告出现的原因与解决方案探索

    我们错误代码的输出到底代表了什么呢?

the *p is 5ffe94.
the p is 1b5d90.
the *p is 12345678.
the p is 5ffe94.

    先看第一行,输出的是变量a存储的内存地址,这是不需要过多解释的,因为我们确实使指针指向的地址中存放了a的地址。但这也是导致警告出现的原因,*p指向的数据是int类型,而&a返回的是int*类型,这是不匹配的。

the *p is 5ffe94.

    于是我想,那我强制类型转换成int类型不就完了,遂修改代码如下。

#include <stdio.h>

int main()
{
    int a = 0x12345678;
    int *p;

    *p = (int) &a;
    printf("the *p is %x.\n", *p);
    printf("the p is %x.\n", p);

    p = &a;
    printf("the *p is %x.\n", *p);
    printf("the p is %x.\n", p);

}

    结果是,喜提新的Warning:cast to pointer from integer of different size。就是说赋的值和指针具有不同的大小,我们可以用sizeof看看*p和&a的大小,再进一步选择强制类型转换的类型。

    printf("the length of *p is %d.\n", sizeof(*p));
    printf("the length of &a is %d.\n", sizeof(&a));

    得到的结果如下所示。

the length of *p is 4.
the length of &a is 8.

    这意味着如果我们要实现把a的地址存放在内存中并能通过指针正常访问的功能,我们应当让计算机以8字节/单位去访问内存,而非我们定义的int *p(即以4字节/单位去访问内存)。那就得在定义指针变量时就进行修改——嚯!坑越挖越大!

    于是再修改代码,long long int类型的变量正是8字节的,于是定义一个long long int*类型的指针,让计算机以8个字节/单位去访问内存。

int main()
{
    int a = 0x12345678;
    long long int *p;
    
    printf("the length of *p is %d.\n", sizeof(*p));
    printf("the length of &a is %d.\n", sizeof(&a));

    *p = (long long int)&a;
    printf("the *p is %x.\n", *p);
    printf("the p is %x.\n", p);


}

    这下得到的输出如下图所示,编译器也没有报错了。

the length of *p is 8.
the length of &a is 8.
the *p is 5ffe94.
the p is 1d5d90.

2.3 进一步思考

    在2.1中,第二行输出的是一个不知道怎么来的地址,而且多次编译,运行后得到的还不一样!如下图所示是连续两次编译得到的输出结果,可以看到第一次输出的是9e5d90,第二次则是195d90。

    多编译几次,还能得到更多不同的输出结果,有时会相同,但奇怪的是他们末尾都是‘5d90’。

    这是因为如果我们没有在初始化时指定指针指向的地址,系统就会让其指向一段随机内存,这段内存是什么形式的(可读?可写?不可访问?合法的?非法的?)我们是不知道的,这就可能引起严重的问题,这种问题就是我们常说的“野指针”问题。

3 总结与唠嗑环节

    这下对C语言指针的理解更深了!如文章内容有不妥或鄙人有理解错误的地方,还请路过的大佬不吝赐教!继续学习,继续热爱!

n file included from src/lab1/step1/step1.c:1:0: src/lab1/step1/../linklist.h: In function ‘addPoly’: src/lab1/step1/../linklist.h:62:7: error: expected identifier or ‘(’ before numeric constant PNODE 1=polyAddLeft->next; ^ src/lab1/step1/../linklist.h:65:8: warning: comparison between pointer and integer while(1!=NULL && r!=NULL) ^~ src/lab1/step1/../linklist.h:67:7: error: invalid type argument of ‘->’ (have ‘int’) if(1->exp==r->exp) ^~ src/lab1/step1/../linklist.h:70:16: error: invalid type argument of ‘->’ (have ‘int’) temp->exp=1->exp; ^~ src/lab1/step1/../linklist.h:71:17: error: invalid type argument of ‘->’ (have ‘int’) temp->coef=1->coef+r->coef; ^~ src/lab1/step1/../linklist.h:75:8: error: invalid type argument of ‘->’ (have ‘int’) 1=1->next; ^~ src/lab1/step1/../linklist.h:78:12: error: invalid type argument of ‘->’ (have ‘int’) else if(1->exp < r->exp) ^~ src/lab1/step1/../linklist.h:81:16: error: invalid type argument of ‘->’ (have ‘int’) temp->exp=1->exp; ^~ src/lab1/step1/../linklist.h:82:17: error: invalid type argument of ‘->’ (have ‘int’) temp->coef=1->coef; ^~ src/lab1/step1/../linklist.h:86:8: error: invalid type argument of ‘->’ (have ‘int’) 1=1->next; ^~ src/lab1/step1/../linklist.h:98:7: warning: comparison between pointer and integer if(1==NULL) sign=r; ^~ src/lab1/step1/../linklist.h:99:20: warning: assignment makes pointer from integer without a cast [-Wint-conversion] if(r==NULL) sign=1; ^ src/lab1/step1/../linklist.h: In function ‘printPoly’: src/lab1/step1/../linklist.h:132:7: error: expected ‘;’ before ‘printf’ printf("%dx^%d",p->coef,p->exp) ^~~~~~
03-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值