鱼C论坛

 找回密码
 立即注册
楼主: 竹逸

[已解决]malloc函数申请的内存空间为什么要进行类型强制转换?

[复制链接]
发表于 2022-11-26 14:34:48 | 显示全部楼层
竹逸 发表于 2022-11-26 14:26
好神奇,为什么我问问题之前,和你同样的代码无法编译,现在又能编译了你看我问题描述,描述 ...

17楼有间接答案
因为我已经回答了这个问题,在前面

再复制一遍
'''
先把我的回复从上到下看一遍,然后再提出你的问题
'''
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 14:38:32 | 显示全部楼层
竹逸 发表于 2022-11-26 14:26
好神奇,为什么我问问题之前,和你同样的代码无法编译,现在又能编译了你看我问题描述,描述 ...

         不使用强制转换 VC 可以正常编译,int * 和 char * 型的都可以,但是 gcc 不行,哪怕是 char * 型的都不行。

  1. D:\[00.Exerciese.2022]\C>g++ -o x x.c
  2. x.c: In function 'int main()':
  3. x.c:6:25: error: invalid conversion from 'void*' to 'int*' [-fpermissive]
  4.          int * p = malloc(4) ;
  5.                          ^
  6. D:\[00.Exerciese.2022]\C>g++ -o x x.c
  7. x.c: In function 'int main()':
  8. x.c:6:26: error: invalid conversion from 'void*' to 'char*' [-fpermissive]
  9.          char * p = malloc(4) ;
  10.                           ^
  11. D:\[00.Exerciese.2022]\C>
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-26 14:42:54 | 显示全部楼层
本帖最后由 竹逸 于 2022-11-26 14:46 编辑


你的代码没问题,我都看了,是我的编译器有问题,我用的是vc6,在问问题之前不强制转换会无法编译,才会发这个帖子,现在又可以编译了,这就见鬼了,我那自己的理解是根据无法编译得出理解的,要是能编译也就不会那样理解了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 14:51:19 | 显示全部楼层
void *可以隐式转换到任何其他指针类型
任何其他指针类型也可以隐式转换到void *
这没有任何问题

下面的代码没有语法错误,运行也不会报错,运行结果没有意义,就仅仅是为了说明这个结论
  1. sh-5.1$ cat main.c
  2. #include <stdio.h>

  3. void *func(void *data) {
  4.     char *c = data;
  5.     *c = '0';
  6.     return data + 1;
  7. }

  8. int main(void) {
  9.     int x = 123;
  10.     float *pf = func(&x);
  11.     unsigned char *c = func(pf);
  12.     *c = '1';
  13.     printf("%x\n", x);
  14.     return 0;
  15. }
  16. sh-5.1$ gcc -g -Wall -o main main.c
  17. sh-5.1$ ./main
  18. 313030
  19. sh-5.1$
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 14:52:33 | 显示全部楼层
竹逸 发表于 2022-11-26 14:42
你的代码没问题,我都看了,是我的编译器有问题,我用的是vc6,在问问题之前不强制转换会无法编译,才 ...

6楼也看了,能不能看懂?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-26 14:59:26 | 显示全部楼层
人造人 发表于 2022-11-26 14:51
void *可以隐式转换到任何其他指针类型
任何其他指针类型也可以隐式转换到void *
这没有任何问题

在VC6里你这代码报错,报错原因:'void *' : unknown size

VC6真的要扔掉了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-26 15:00:41 | 显示全部楼层
人造人 发表于 2022-11-26 14:52
6楼也看了,能不能看懂?

能,你的代码都看得懂,是VC6编译器的问题,我的任何理解都是根据编译器的结果来推导的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 15:07:50 | 显示全部楼层
memset这个函数用来初始化一段内存空间
  1.        void *memset(void *s, int c, size_t n);
复制代码

这是这个函数的声明,看到了吧,void * 类型的
可是你写代码的时候强制转换到void * 了?
memset((void *)a, 0, sizeof(int) * 10);
但是为什么你们就是要这样写代码?
int *a = (int *)malloc(sizeof(int) * 10);
为什么就是要强制转换?这不是都一样么?
要么都转,要么都不转,这是为了统一编码风格,这我能理解,但是为什么就是要对malloc区别对待?

你说你要让这个代码在C++中也可用?
是的,在C++中如果不强制转换类型,是会编译报错的,因为C++中void *和其他指针类型不在隐式转换
但是我想说,你在C++中用什么malloc/free,C++中有自己的,很好用的new/delete你不用,你就是要用C的malloc/free ?
你是闲bug不够多是不是?
C++中用malloc/free是很有可能会出问题的


  1. sh-5.1$ cat main.c
  2. #include <stdio.h>
  3. #include <string.h>

  4. int main(void) {
  5.     int a[10];
  6.     memset(a, 0, sizeof(int) * 10);
  7.     //memset((void *)a, 0, sizeof(int) * 10);
  8.     return 0;
  9. }
  10. sh-5.1$ gcc -g -Wall -o main main.c
  11. sh-5.1$
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 15:17:05 | 显示全部楼层
竹逸 发表于 2022-11-26 15:00
能,你的代码都看得懂,是VC6编译器的问题,我的任何理解都是根据编译器的结果来推导的

你还是没看懂呀,那我就解释一下吧
一开始这个代码用C编译器gcc编译,没有问题
然后又用C++编译器g++编译,是同一个代码,但是报错了
因为
C中void *和其他指针类型是可以隐式转换的
而C++中void *和其他指针类型不在隐式转换
所以在C++中得强制转换
这就是这个写法的来源
int *a = (int *)malloc(sizeof(int) * 10);
因为报错了,然后看到有人说强制转换一下,他们强制转换了,然后就正常了,然后他们就记住了,用malloc一定要强制转换,不然是会报错的
可是,他们根本就没有意识到他们是在用C++环境学C语言
说简单点就是,他们在用C++的编译器编译C语言的代码
那么问题来了,这个他们里面有没有你?
你看一下你的源代码文件名的后缀是不是 .c,.c是C语言,.cpp是C++
你再检查一下你是不是用的C++编译器

  1. sh-5.1$ cat main.c
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. int main(void) {
  5.     char *a = malloc(3);
  6.     a[0] = 'o';
  7.     a[1] = 'k';
  8.     a[2] = '\0';
  9.     puts(a);
  10.     free(a);
  11.     return 0;
  12. }
  13. sh-5.1$ gcc -g -Wall -o main main.c
  14. sh-5.1$ ./main
  15. ok
  16. sh-5.1$ g++ -g -Wall -o main main.c
  17. main.c: In function ‘int main()’:
  18. main.c:5:21: error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive]
  19.     5 |     char *a = malloc(3);
  20.       |               ~~~~~~^~~
  21.       |                     |
  22.       |                     void*
  23. sh-5.1$
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 15:19:06 | 显示全部楼层
我的每一个回复对你都是有帮助的,希望不要忽略
如果哪个看不懂的话,说出来,我给你解释
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-26 15:20:45 | 显示全部楼层
人造人 发表于 2022-11-26 15:17
你还是没看懂呀,那我就解释一下吧
一开始这个代码用C编译器gcc编译,没有问题
然后又用C++编译器g++编 ...

我用的是VC6编译器,不知道是不是C++编译器,虽然代码文件的后缀是 .c
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 15:26:00 | 显示全部楼层
竹逸 发表于 2022-11-26 15:20
我用的是VC6编译器,不知道是不是C++编译器,虽然代码文件的后缀是 .c

我很久之前就不用vc6了,我也不知道
不过如果你的后缀是 .c 的话,问题应该不大
建议还是换一个好点的编译器吧
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 15:30:46 | 显示全部楼层
竹逸 发表于 2022-11-26 13:35
我发现不进行类型转换,可以用字符型指针来接收这段空间的起始地址,但int型指针就无法编译

所以为什么无法编译呢?
很奇怪,一定是你的操作不对,你再想想,想想你是怎么操作的,为什么会无法编译呢?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-26 15:49:11 | 显示全部楼层
人造人 发表于 2022-11-26 15:30
所以为什么无法编译呢?
很奇怪,一定是你的操作不对,你再想想,想想你是怎么操作的,为什么会无法编译 ...

问问题之前代码绝对没问题,我保证代码的正确性,就是不知道为啥无法编译,可能是和上一个打开的文件有关?复制了你的代码,重新编译下就又能编译了,我也觉得奇怪的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 15:58:40 | 显示全部楼层
竹逸 发表于 2022-11-26 14:21
是的,我学汇编的时候就是小甲鱼8086的CPU知识,所以也就只能用8086的来描述,而且malloc函数却是也是从 ...

那就用16位的汇编语言来研究也是可以的,你现在应该就差一个tc编译器了吧,弄一个
tc是16位的C语言编译器
可以用tc编译器来编译C语言代码,用debug这个软件来反汇编
如果你有兴趣的话,可以研究研究下面的反汇编代码

1.png
2.png
3.png
4.png

  1. 11B3:0291 55            PUSH    BP
  2. 11B3:0292 8BEC          MOV     BP,SP
  3. 11B3:0294 56            PUSH    SI
  4. 11B3:0295 B89102        MOV     AX,0291
  5. 11B3:0298 50            PUSH    AX
  6. 11B3:0299 B8AA00        MOV     AX,00AA
  7. 11B3:029C 50            PUSH    AX
  8. 11B3:029D E8630C        CALL    0F03
  9. 11B3:02A0 59            POP     CX
  10. 11B3:02A1 59            POP     CX
  11. 11B3:02A2 B80600        MOV     AX,0006
  12. 11B3:02A5 50            PUSH    AX
  13. 11B3:02A6 E8CE08        CALL    0B77
  14. 11B3:02A9 59            POP     CX
  15. 11B3:02AA 8BF0          MOV     SI,AX
  16. 11B3:02AC C7046400      MOV     WORD PTR [SI],0064
  17. 11B3:02B0 C74402C800    MOV     WORD PTR [SI+02],00C8
  18. 11B3:02B5 8B04          MOV     AX,[SI]
  19. 11B3:02B7 034402        ADD     AX,[SI+02]
  20. 11B3:02BA 894404        MOV     [SI+04],AX
  21. 11B3:02BD FF7404        PUSH    [SI+04]
  22. 11B3:02C0 B8B400        MOV     AX,00B4
  23. 11B3:02C3 50            PUSH    AX
  24. 11B3:02C4 E83C0C        CALL    0F03
  25. 11B3:02C7 59            POP     CX
  26. 11B3:02C8 59            POP     CX
  27. 11B3:02C9 56            PUSH    SI
  28. 11B3:02CA E8DB07        CALL    0AA8
  29. 11B3:02CD 59            POP     CX
  30. 11B3:02CE 33C0          XOR     AX,AX
  31. 11B3:02D0 EB00          JMP     02D2
  32. 11B3:02D2 5E            POP     SI
  33. 11B3:02D3 5D            POP     BP
  34. 11B3:02D4 C3            RET

复制代码


其实你应该尽快的往后学,后面有更好的,更方便的工具
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 15:59:51 | 显示全部楼层
竹逸 发表于 2022-11-26 15:49
问问题之前代码绝对没问题,我保证代码的正确性,就是不知道为啥无法编译,可能是和上一个打开的文件有关 ...

这个我就不知道了,不过我感觉就是你的操作问题
^_^
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-26 16:05:09 | 显示全部楼层
人造人 发表于 2022-11-26 15:58
那就用16位的汇编语言来研究也是可以的,你现在应该就差一个tc编译器了吧,弄一个
tc是16位的C语言编译 ...

汇编代码看着 头疼,我才学了一点点,没学完
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 16:05:47 | 显示全部楼层
竹逸 发表于 2022-11-26 16:05
汇编代码看着 头疼,我才学了一点点,没学完

^_^
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 16:09:19 | 显示全部楼层
jackz007 发表于 2022-11-26 14:28
你不用关心堆指针的事情,因为,这个完全是由操作系统在掌控(malloc() 是 Windows API),你 ...

malloc() 是 Windows API

malloc 不是 windows api,malloc是C语言的库函数
linux下面的C语言也可以使用malloc函数
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-26 16:10:43 | 显示全部楼层
jackz007 发表于 2022-11-26 14:38
不使用强制转换 VC 可以正常编译,int * 和 char * 型的都可以,但是 gcc 不行,哪怕是 char *  ...

因为你使用的g++,这是C++编译器
gcc才是C语言编译器
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-14 00:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表