人造人 发表于 2022-11-26 14:34:48

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

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

再复制一遍
'''
先把我的回复从上到下看一遍,然后再提出你的问题
'''

jackz007 发表于 2022-11-26 14:38:32

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

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

D:\\C>g++ -o x x.c
x.c: In function 'int main()':
x.c:6:25: error: invalid conversion from 'void*' to 'int*' [-fpermissive]
         int * p = malloc(4) ;
                         ^
D:\\C>g++ -o x x.c
x.c: In function 'int main()':
x.c:6:26: error: invalid conversion from 'void*' to 'char*' [-fpermissive]
         char * p = malloc(4) ;
                        ^
D:\\C>

竹逸 发表于 2022-11-26 14:42:54

本帖最后由 竹逸 于 2022-11-26 14:46 编辑

人造人 发表于 2022-11-26 14:32
17楼
https://fishc.com.cn/forum.php?mod=redirect&goto=findpost&ptid=221281&pid=6063298

你的代码没问题,我都看了,是我的编译器有问题,我用的是vc6,在问问题之前不强制转换会无法编译,才会发这个帖子,现在又可以编译了,这就见鬼了,我那自己的理解是根据无法编译得出理解的,要是能编译也就不会那样理解了{:5_99:}

人造人 发表于 2022-11-26 14:51:19

void *可以隐式转换到任何其他指针类型
任何其他指针类型也可以隐式转换到void *
这没有任何问题

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

void *func(void *data) {
    char *c = data;
    *c = '0';
    return data + 1;
}

int main(void) {
    int x = 123;
    float *pf = func(&x);
    unsigned char *c = func(pf);
    *c = '1';
    printf("%x\n", x);
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
sh-5.1$ ./main
313030
sh-5.1$

人造人 发表于 2022-11-26 14:52:33

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

6楼也看了,能不能看懂?

竹逸 发表于 2022-11-26 14:59:26

人造人 发表于 2022-11-26 14:51
void *可以隐式转换到任何其他指针类型
任何其他指针类型也可以隐式转换到void *
这没有任何问题


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

VC6真的要扔掉了

竹逸 发表于 2022-11-26 15:00:41

人造人 发表于 2022-11-26 14:52
6楼也看了,能不能看懂?

能,你的代码都看得懂,是VC6编译器的问题,我的任何理解都是根据编译器的结果来推导的{:5_99:}

人造人 发表于 2022-11-26 15:07:50

memset这个函数用来初始化一段内存空间
       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是很有可能会出问题的


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

int main(void) {
    int a;
    memset(a, 0, sizeof(int) * 10);
    //memset((void *)a, 0, sizeof(int) * 10);
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
sh-5.1$

人造人 发表于 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++编译器

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

int main(void) {
    char *a = malloc(3);
    a = 'o';
    a = 'k';
    a = '\0';
    puts(a);
    free(a);
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
sh-5.1$ ./main
ok
sh-5.1$ g++ -g -Wall -o main main.c
main.c: In function ‘int main()’:
main.c:5:21: error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive]
    5 |   char *a = malloc(3);
      |               ~~~~~~^~~
      |                     |
      |                     void*
sh-5.1$

人造人 发表于 2022-11-26 15:19:06

我的每一个回复对你都是有帮助的,希望不要忽略
如果哪个看不懂的话,说出来,我给你解释

竹逸 发表于 2022-11-26 15:20:45

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

我用的是VC6编译器,不知道是不是C++编译器,虽然代码文件的后缀是 .c{:5_94:}

人造人 发表于 2022-11-26 15:26:00

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

我很久之前就不用vc6了,我也不知道
不过如果你的后缀是 .c 的话,问题应该不大
建议还是换一个好点的编译器吧

人造人 发表于 2022-11-26 15:30:46

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

所以为什么无法编译呢?
很奇怪,一定是你的操作不对,你再想想,想想你是怎么操作的,为什么会无法编译呢?

竹逸 发表于 2022-11-26 15:49:11

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

问问题之前代码绝对没问题,我保证代码的正确性,就是不知道为啥无法编译,可能是和上一个打开的文件有关?复制了你的代码,重新编译下就又能编译了,我也觉得奇怪的{:5_99:}

人造人 发表于 2022-11-26 15:58:40

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

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






11B3:0291 55            PUSH    BP
11B3:0292 8BEC          MOV   BP,SP
11B3:0294 56            PUSH    SI
11B3:0295 B89102      MOV   AX,0291
11B3:0298 50            PUSH    AX
11B3:0299 B8AA00      MOV   AX,00AA
11B3:029C 50            PUSH    AX
11B3:029D E8630C      CALL    0F03
11B3:02A0 59            POP   CX
11B3:02A1 59            POP   CX
11B3:02A2 B80600      MOV   AX,0006
11B3:02A5 50            PUSH    AX
11B3:02A6 E8CE08      CALL    0B77
11B3:02A9 59            POP   CX
11B3:02AA 8BF0          MOV   SI,AX
11B3:02AC C7046400      MOV   WORD PTR ,0064
11B3:02B0 C74402C800    MOV   WORD PTR ,00C8
11B3:02B5 8B04          MOV   AX,
11B3:02B7 034402      ADD   AX,
11B3:02BA 894404      MOV   ,AX
11B3:02BD FF7404      PUSH   
11B3:02C0 B8B400      MOV   AX,00B4
11B3:02C3 50            PUSH    AX
11B3:02C4 E83C0C      CALL    0F03
11B3:02C7 59            POP   CX
11B3:02C8 59            POP   CX
11B3:02C9 56            PUSH    SI
11B3:02CA E8DB07      CALL    0AA8
11B3:02CD 59            POP   CX
11B3:02CE 33C0          XOR   AX,AX
11B3:02D0 EB00          JMP   02D2
11B3:02D2 5E            POP   SI
11B3:02D3 5D            POP   BP
11B3:02D4 C3            RET



其实你应该尽快的往后学,后面有更好的,更方便的工具

人造人 发表于 2022-11-26 15:59:51

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

这个我就不知道了,不过我感觉就是你的操作问题
^_^

竹逸 发表于 2022-11-26 16:05:09

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

汇编代码看着 头疼,我才学了一点点,没学完{:5_99:}

人造人 发表于 2022-11-26 16:05:47

竹逸 发表于 2022-11-26 16:05
汇编代码看着 头疼,我才学了一点点,没学完

^_^

人造人 发表于 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函数

人造人 发表于 2022-11-26 16:10:43

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

因为你使用的g++,这是C++编译器
gcc才是C语言编译器
页: 1 [2] 3
查看完整版本: malloc函数申请的内存空间为什么要进行类型强制转换?