地址与指针类型不兼容造成的影响
最近在复习C语言的语法,复习到指针的时候,看到自己的笔记写着“指针类型要与地址兼容”,换句话说就是“指针类型和所指数据的类型要一致”,当时还在旁边配着一小段代码。
int num01 = 18;
double num02 = 3.14;
int* point01 = &num01; //√
double* point02 = &num02; //√
double* point03 = &num01; //×
假设我非要用double类型的指针指向int型的变量,“地址与指针类型不兼容”会造成什么影响呢?
接下来我们来写一个程序。
#include "stdio.h"
int main() {
/*
* 32位机,int类型占4个字节
* 十六进制:0x 00 11 11 11
* 十进制:1118481
* 二进制:0b 00000000 00010001 00010001 00010001
*/
int intNum = 1118481;
int* intPoint = &intNum;
//char型指针指向int型变量
char* charPoint = &intNum;
printf("===================\n");
printf("sizeof(intPoint) = %d\n", sizeof(intPoint));
printf("sizeof(charPoint) = %d\n", sizeof(charPoint));
printf("===================\n");
printf("intPoint: %p\n", intPoint);
printf("charPoint: %p\n", charPoint);
printf("===================\n");
intPoint++;
charPoint++;
printf("intPoint++: %p\n", intPoint);
printf("charPoint++: %p\n", charPoint);
printf("===================\n");
char charNum = 'a';
//int型指针指向char型变量
intPoint = &charNum;
charPoint = &charNum;
printf("intPoint: %p\n", intPoint);
printf("charPoint: %p\n", charPoint);
printf("===================\n");
intPoint++;
charPoint++;
printf("intPoint++: %p\n", intPoint);
printf("charPoint++: %p\n", charPoint);
printf("===================\n");
return 0;
}
/*
结果:
1、32位机,用4字节存储地址,所有sizeof都为4
sizeof(intPoint) = 4
sizeof(charPoint) = 4
2、两个指针都指向同一个地址,即0x 00 B3 F9 E0
intPoint: 00B3F9E0
charPoint: 00B3F9E0
3、因为int类型占4个字节,char类型占1个字节。
所以int型指针的增量为4字节,char型指针为1字节
intPoint++: 00B3F9E4
charPoint++: 00B3F9E1
4、两个指针都指向同一个地址,即0x 00 B3 F9 E0
intPoint: 00B3F9BF
charPoint: 00B3F9BF
5、因为int类型占4个字节,char类型占1个字节。
所以int型指针的增量为4字节,char型指针为1字节
intPoint++: 00B3F9C3
charPoint++: 00B3F9C0
*/
由上可得,程序可以编译并且运行成功。重点是int型的指针和char型指针同时指向同一个变量时,最初指针变量的值(即指向的地址)都是一样的,但是执行完自增操作后值就不同了。
为何呢?
指针的两个语义:一是内存的基地址,即变量存放的地址;二是指向数据的类型,即变量所占的内存空间。
如我刚刚演示的程序,在32位的环境下,int型占4个字节,所以int型的指针自增就是以4个字节为增量。
接下来,我们再举一个列子来说明,类型不兼容的影响。
32位机,int类型占4个字节
我们用8个字节,即2个int型或者8个char型来实验
int型数字1:
十六进制:0x 41 42 43 44
十进制:0d 1094861636
二进制:0b 01000001 01000010 01000011 01000100
int型数字2:
十六进制:0x 45 46 47 48
十进制:0d 1162233672
二进制:0b 01000101 01000110 01000111 01001000
8 个char型变量与其对应的二进制、十进制
'A' --> 0b 01000001 --> 0d 65
'B' --> 0b 01000010 --> 0d 66
'C' --> 0b 01000011 --> 0d 67
'D' --> 0b 01000100 --> 0d 68
'E' --> 0b 01000101 --> 0d 69
'F' --> 0b 01000110 --> 0d 70
'G' --> 0b 01000111 --> 0d 71
'H' --> 0b 01001000 --> 0d 72
#include "stdio.h"
void printChar(char* start, char* end);
void printInt(int* start, int* end);
int main() {
printf("=================================\n");
char charArr[8] = { 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A' };
printf("sizeof(charArr)/sizeof(char) = %d\n", sizeof(charArr) / sizeof(char));
printf("sizeof(charArr)/sizeof(int) = %d\n", sizeof(charArr) / sizeof(int));
printf("=================================\n");
//char型指针指向char型变量
char* charPoint01 = charArr;
//int型指针指向char型变量
int* intPoint01 = charArr;
printChar(charPoint01, charPoint01 + sizeof(charArr) / sizeof(char));
printInt(intPoint01, intPoint01 + sizeof(charArr) / sizeof(int));
printf("=================================\n");
int intArr[2] = { 1162233672, 1094861636 };
printf("sizeof(intArr)/sizeof(char) = %d\n", (sizeof(intArr)) / sizeof(char));
printf("sizeof(intArr)/sizeof(int) = %d\n", sizeof(intArr) / sizeof(int));
printf("=================================\n");
int* intPoint02 = intArr;
char* charPoint02 = intArr;
printChar(charPoint02, charPoint02 + 8);
printInt(intPoint02, intPoint02 + sizeof(charArr) / sizeof(int));
printf("=================================\n");
return 0;
}
void printChar(char* start, char* end) {
while (start < end) {
printf("%c ", *start);
start++;
}
printf("\n");
}
void printInt(int* start, int* end) {
while (start < end) {
printf("%d ", *start);
start++;
}
printf("\n");
}
/*
结果:
=================================
sizeof(charArr)/sizeof(char) = 8
sizeof(charArr)/sizeof(int) = 2
=================================
H G F E D C B A
1162233672 1094861636
=================================
sizeof(intArr)/sizeof(char) = 8
sizeof(intArr)/sizeof(int) = 2
=================================
H G F E D C B A
1162233672 1094861636
=================================
*/
由此得出,我们将2个int型的数据,其在内存中的存储占8个字节,int型指针会一次读取4个字节,可以正常显示2个int型变量。
但是如果我们错误地将char型指针指向int型变量,char型数据在内存中占1个字节,char型指针一个只会读取1个字节的数据,因为就会将2个int型变量输出成8个char型变量,造成数据截断。
综上所述,指针类型和其所指向的数据类型要一致,即“地址和指针类型兼容”,否则在进行“指针操作”时会出现诸多问题。
注:如有错误,敬请指正!!!