为什么不同类型的指针用于c中的不同数据类型?
如果我们必须保存任何数据类型的地址,那么我们需要该数据类型的指针。 但是指针只是一个地址,并且地址总是int
类型,那么为什么任何数据类型的保持地址都需要该类型的指针?
有几个原因:
- 并非所有地址都是平等的; 特别是,在非Von Neuman(例如Harvard )架构中,指向代码存储器的指针(通常存储常量)和指向数据存储器的指针是不同的。
- 您需要知道基础类型才能正确执行访问。 例如,读取或写入
char
不同于读取或写入double
char
。 - 您需要其他信息来执行指针运算。
请注意,在C中有一个指针类型,意思是“简单的指针”,称为void*
。 您可以使用此指针在内存中传输地址,但是您需要将其转换为有用的内容,以便在void*
指向的内存中执行操作。
指针不只是int
。 它们含蓄地具有语义。
以下是几个例子:
-
p->member
只有在知道p
指向的类型时才有意义。 -
p = p+1;
根据您指向的对象的大小而行为不同(在某种意义上,’p’实际上增加了,当被视为无符号整数时,它指向的类型的大小)。
您可以非常轻松地在C中使用无类型指针 – 您只需对所有指针使用void *
。 尽管出于两个我能想到的原因,这将是相当愚蠢的。
首先,通过指定类型中指向的数据,编译器可以避免许多愚蠢的错误,拼写错误或其他错误。 相反,如果你剥夺编译器的这些信息,你必须花很多时间来调试那些本来不应该成为问题的事情。
另外,你可能使用过“指针运算”。 例如, int *pInt = &someInt; pInt++;
int *pInt = &someInt; pInt++;
– 将指针前进到内存中的下一个整数; 无论类型如何,它都可以工作,并前进到正确的地址,但它只有在编译器知道所指向的大小时才能工作。
以下示例有助于理解不同类型的指针之间的差异:
#include int main() { // pointer to char char * cp = "Abcdefghijk"; // pinter to int int * ip = (int *)cp; // to the same address // try address arithmetic printf("Test of char*:\n"); printf("address %p contains data %c\n", cp, *cp); printf("address %p contains data %c\n", (cp+1), *(cp+1)); printf("Test of int*:\n"); printf("address %p contains data %c\n", ip, *ip); printf("address %p contains data %c\n", (ip + 1), *(ip + 1)); return 0; }
输出是
重要的是要理解address+1
表达式根据address
类型给出不同的结果,即+1
表示sizeof(addressed data)
,如sizeof(*address)
。
因此,如果在您的系统(对于您的编译器) sizeof(int)
和sizeof(char)
不同(例如4和1), cp+1
和ip+1
的结果也不同。 在我的系统中它是:
E05859(hex) - E05858(hex) = 14702684(dec) - 14702681(dec) = 1 byte for char E0585C(hex) - E05858(hex) = 14702684(dec) - 14702680(dec) = 4 bytes for int
注意:在这种情况下,具体的地址值并不重要,唯一的区别很重要。
更新:
顺便说一下,地址(指针)算术不受+1
或++
限制,可以做出很多例子,例如:
int arr[] = { 1, 2, 3, 4, 5, 6 }; int *p1 = &arr[1]; int *p4 = &arr[4]; printf("Distance between %d and %d is %d\n", *p1, *p4, p4 - p1); printf("But addresses are %p and %p have absolute difference in %d\n", p1, p4, int(p4) - int(p1));
与输出
因此,为了更好地理解阅读教程
因为你假设“地址总是int类型”是错误的。
完全有可能创建一个计算机体系结构,例如,由于某种原因,指向字符的指针大于指向单词的指针。 C会处理这个问题。
此外,当然,指针可以被取消引用 ,当您这样做时,编译器需要知道您希望在相关地址找到的数据类型。 否则它无法生成处理该数据的正确指令。
考虑:
char *x = malloc(sizeof *x); *x = 0; double *y = malloc(sizeof *y); *y = 0;
这两个片段将写入完全不同的内存量(或者如果分配失败则会爆炸,暂时不用,但实际的文字常量( 0
为int
类型)在两种情况下都是相同的。 有关指针类型的信息允许编译器生成正确的代码。
这主要是针对那些在您之后阅读代码的人,因此他们可以知道存储在该地址的内容。 此外,如果你在你的代码中做任何指针算术,编译器需要知道如果你执行像指针类型给出的pSomething ++这样的东西,他应该向前推进多少,因为你的数据类型的大小是编译前已知。
因为指针的类型告诉编译器,一次可以执行多少字节的操作。
示例: – 如果char只有1个字节
在int 2字节的情况下可能会有所不同。