今天看到了一个问题:c里面,不同类型的指针是否可以互指呢?也就是不同类型的指针之间是否可以互相赋值,我想了想,对于32位机子而言,所有类型的指针都是4Byte(64位就是8Byte,这里只讨论32位),为什么是4Byte呢,原因是32位的机子,内存的地址值就是32位,也就是4Byte,而所有的指针,都是存着内存中某个地址的值的,所以所有类型的指针都是32位。既然如此,理应可以相互赋值啊,于是好奇地敲了两行小代码来尝试一下。首先尝试的代码是这样的:
1 int *p1 = (int*)malloc(10*sizeof(int)); 2 int i; 3 for(i = 0; i < 10; ++i){ 4 p1[i] = 1; 5 } 6 char *p2 = p1; 7 printf("p1 = %p, p2 = %p\n", p1,p2); 8 if(p1==NULL){ 9 printf("NULL\n"); 10 } else { 11 for (i = 0; i < 10; ++i) 12 { 13 printf("%d",*(p1+i)); 14 } 15 printf("\n"); 16 }
结果编译的时候出现了一个warning,p1和p2都是指向相同的地址没问题,输出结果很正常:
但当我把11行的输出代码换成*(p2+i)的时候,输出结果就不太对了:
这里的输出为什么是1000100010呢?我猜int是4Byte,char是1Byte,所以int*每次移(++)动都会移动4Byte,而char*每次移动(++)则只会移动1Byte,所以这里的1000应该为原来的一个int类型的1,所以我把代码改了一下来验证我的想法:
1 int *p1 = (int*)malloc(10*sizeof(int)); 2 int i; 3 for(i = 0; i < 10; ++i){ 4 p1[i] = 1; 5 } 6 char *p2 = p1; 7 printf("p1 = %p, p2 = %p\n", p1,p2); 8 if(p1==NULL){ 9 printf("NULL\n"); 10 } else { 11 for (i = 0; i < 10*4; ++i) //4个为1组,10个int对于char*来说一共要移动40次 12 { 13 printf("%d",*(p2+i)); 14 if((i+1)%4==0){ //每4个换行,方便观察输出而已 15 printf("\n"); 16 } 17 }18 }
我想结果应该是1000 1000 1000这样的,结果果然是这样:
因此,我们可以得知,不同类型的指针,虽然都是存放地址,虽然可以互相赋值,但是由于不同类型的大小不同,所以很容易出错,我们还是严格遵循规范比较好。有一个类型就比较特殊,就是void,void*是可以由任意别的类型进行赋值的,我们这里把p2的类型改成void*来进行尝试,发现直接赋值是不会产生任何的warning和error。但是发现,即便取得到地址,也没有办法进行解引用,也就是无法取的这块内存里面存放的值,原因是无法进行类型检测,根本不知道一个数据多大,一跳要跳多少,所以当我们要用void*指针来进行输出,编译时就会出现如下错误: