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语言指针的理解更深了!如文章内容有不妥或鄙人有理解错误的地方,还请路过的大佬不吝赐教!继续学习,继续热爱!

  • 36
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个警告是因为你把一个指针赋值给了一个整型变量。你可以尝试将变量 `temp` 声明为指针类型,或者在赋值时使用强制类型转换。例如: ``` int *temp; temp = (int*)(store + i * SIZE + j); ``` 或者: ``` int temp; temp = (int)(*(store + i * SIZE + j)); ``` 不过需要注意的是,这种类型转换可能会引入潜在的错误,所以建议在使用前多加检查。 ### 回答2: 该警告是由于在第41行的代码中,将指针赋值给整型变量导致。 在这行代码中,temp是一个整型变量,而*(store i * SIZE j)是一个指针。将一个指针赋值给整型变量是不符合语法规则的,因此编译器会给出这个警告。 要解决这个警告,可以通过对指针进行类型转换来解决。即使用强制类型转换将指针转换为整型,然后再进行赋值操作。修改后的代码如下: temp = (int)*(store i * SIZE j); 这样就可以消除这个警告。然而,在进行强制类型转换时应该谨慎,因为如果类型转换不正确,可能会导致程序运行错误。所以在进行类型转换前,应该确保转换的类型是正确的,以避免可能的错误。 在修复警告之后,重新编译代码时,该警告将不再出现。但仍建议在进行类型转换时,仔细检查代码逻辑,确保转换的类型是正确的,并且不会引起其他问题。 ### 回答3: 该警告是由于将一个指针赋值给一个整数而产生的。在Main.c文件的第41行的语句中,将*(store i * SIZE j)的值赋给了一个变量temp。问题出在这里,*(store i * SIZE j)是一个指针,而temp是一个整数变量,将一个指针赋给一个整数不符合C语言的类型匹配规则。 为了解决这个警告,我们需要进行类型转换。可以通过在赋值语句的左边使用强制类型转换符将指针转换为整数,然后再将其赋给temp。这样,编译器就不会报警告了。 修改后的代码如下: temp = (int)(*(store i * SIZE j)); 通过在赋值语句的左边使用(int)将指针*(store i * SIZE j)转换为整数类型,然后再将其赋给temp变量。这样就消除了编译器的警告。 需要注意的是,这种类型转换可能会导致数据截断或数据损失的情况,因此在进行强制类型转换的时候需要谨慎操作,并确保转换后的类型是正确的,并不会引起其他问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值