如果我们必须保存任何数据类型的地址,那么我们需要一个指向该数据类型的指针。
但指针只是一个地址,地址始终是int
类型。那么为什么任何数据类型的保持地址都需要该类型的指针?
答案 0 :(得分:17)
有几个原因:
char
与阅读或撰写double
不同。请注意,在C中有一个指针类型,意思是“只是一个指针”,称为void*
。您可以使用此指针在内存中传输地址,但是您需要将其强制转换为有用的内容,以便在void*
指向的内存中执行操作。
答案 1 :(得分:4)
指针不只是int
。它们含蓄地具有语义。
以下是几个例子:
p->member
只有在知道p
指向的类型时才有意义。
p = p+1;
的行为会有所不同,具体取决于您指向的对象的大小(在某种意义上,'p'实际上会增加,当被视为无符号整数时,按其类型的大小而增加指着)。
答案 2 :(得分:3)
以下示例有助于理解不同类型的指针之间的差异:
#include <stdio.h>
int main()
{
// Pointer to char
char * cp = "Abcdefghijk";
// Pointer 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));
输出:
因此,为了更好地理解,请阅读the tutorial。
答案 3 :(得分:2)
因为你假设“地址总是int类型”是错误的。
完全有可能创建一个计算机体系结构,例如,由于某种原因,指向字符的指针大于指向单词的指针。 C会处理这个问题。
当然,指针也可以取消引用,当你这样做时,编译器需要知道你希望在相关地址找到的数据类型。否则它无法生成处理该数据的正确指令。
考虑:
char *x = malloc(sizeof *x);
*x = 0;
double *y = malloc(sizeof *y);
*y = 0;
这两个片段会写出完全不同的内存量(或者如果分配失败则会爆炸,暂时不用说),但实际的文字常量(0
类型为int
)是两种情况都是一样的。有关指针类型的信息允许编译器生成正确的代码。
答案 4 :(得分:2)
您可以非常轻松地在C中使用无类型指针 - 您只需对所有指针使用void *
。尽管出于两个我能想到的原因,这将是相当愚蠢的。
首先,通过指定类型中指向的数据,编译器可以避免许多愚蠢的错误,拼写错误或其他错误。相反,如果你剥夺编译器的这些信息,你必须花很多时间来调试那些从来不应该成为问题的事情。
此外,您可能使用过“指针算术”。例如,int *pInt = &someInt; pInt++;
- 将指针前进到内存中的下一个整数;无论类型如何,它都可以正常工作,并前进到正确的地址,但只有在编译器知道所指向的内容大小时才能工作。
答案 5 :(得分:0)
这主要是针对那些在您之后阅读代码的人,因此他们可以知道该地址存储的内容。此外,如果你在你的代码中做任何指针算术,编译器需要知道如果你执行像指针类型给出的pSomething ++这样的东西,他应该向前推进多少,因为你的数据类型的大小是在编译之前就知道了。
答案 6 :(得分:0)
因为指针的类型告诉编译器一次可以执行操作的字节数。
示例:在char
的情况下,只有一个字节。并且在两个字节的int的情况下它可能是不同的。