引言:
C语言中不同的数据类型其在计算机内部的存储方式不同,占用内存大小也不同,这是我们能看到的给整型、浮点型...这些区分类型的直接原因。
指针有很多类型,但是无论是哪种类型的指针本质上它们的值都是同一种类型:地址编号;在计算机中的存取方式都是相同的,所占内存大小在同一架构下都是相等的(4or8字节),那么指针还分那么多类型的意义是什么呢?
在C语言中,指针的类型非常重要,它不仅决定了指针访问的内存大小,还决定了指针在访问内存时的步长。下面是一些示例代码,演示了指针类型的意义。
示例1:解引用时访问的内存大小不同
#include <stdio.h>
int main()
{
int a = 0x12345678;
char* p = (char*)&a;
printf("a = 0x%x\n", a);
printf("p[0] = 0x%x\n", p[0]);
printf("p[1] = 0x%x\n", p[1]);
printf("p[2] = 0x%x\n", p[2]);
printf("p[3] = 0x%x\n", p[3]);
return 0;
}
在这个示例中,我们将一个int型变量a的地址赋给了一个char类型的指针p。在使用指针p访问内存时,我们只能访问a中的一个字节。这是因为char类型的指针只能解引用一个字节的内存,而int型变量通常占用4个字节的内存。
C的这个特性有一个经典的用法:测试机器的大小端:
以下是可以检测机器大小端的C语言代码:
#include <stdio.h>
int main()
{
unsigned int i = 1;
char* c = (char*)&i;
if (*c == 1)
{
printf("Little Endian\n");
}
else
{
printf("Big Endian\n");
}
return 0;
}
在这个示例中,我们定义了一个unsigned int型变量i,并将它的地址赋给了一个char*类型的指针c。然后,我们通过判断指针c所指向的内存中的第一个字节的值,来确定机器的大小端模式。如果第一个字节的值为1,则说明机器是小端模式;否则,说明机器是大端模式。
注意,这个方法只适用于检测基本数据类型的大小端。对于复杂的数据类型,可能会有不同的字节顺序。因此,在实际编程中,需要根据实际情况选择合适的方法来检测大小端。
示例2:指针的步长不同
#include <stdio.h>
int main()
{
int a[3] = {1, 2, 3};
int* p1 = a;
char* p2 = (char*)a;
printf("p1 = %p, p2 = %p\n", p1, p2);
printf("p1 + 1 = %p, p2 + 1 = %p\n", p1 + 1, p2 + 1);
printf("*p1 = %d, *p2 = %d\n", *p1, *p2);
printf("*(p1 + 1) = %d, *(p2 + 1) = %d\n", *(p1 + 1), *(p2 + 1));
return 0;
}
在这个示例中,我们定义了一个int型数组a,然后将它的地址分别赋给了一个int类型的指针p1和一个char类型的指针p2。在使用指针p1和p2进行加减运算时,它们所跨越的步长是不同的。指针p1每次加1时,它所指向的地址会增加4个字节;而指针p2每次加1时,它所指向的地址只会增加1个字节。因此,在使用指针进行数组操作时,需要根据数组元素的类型选择合适的指针类型。
总结
指针类型在C语言中非常重要,它不仅决定了指针所占用的内存大小,还决定了指针在访问内存时的步长。在使用指针时,需要根据实际情况选择合适的指针类型,以便灵活地控制要访问一个数据中的多少内存。这也是C语言强大的原因之一,它可以让程序员灵活地控制内存,实现各种复杂的任务