为什么C中的不同数据类型有不同类型的指针?

时间:2012-09-21 12:40:58

标签: c

如果我们必须保存任何数据类型的地址,那么我们需要一个指向该数据类型的指针。

但指针只是一个地址,地址始终是int类型。那么为什么任何数据类型的保持地址都需要该类型的指针?

7 个答案:

答案 0 :(得分:17)

有几个原因:

  • 并非所有地址都是平等的;特别是在非Von Neuman(例如Harvard)体系结构中,指向代码存储器的指针(通常存储常量)和指向数据存储器的指针是不同的。
  • 您需要知道基础类型才能正确执行访问。例如,阅读或撰写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;
}

输出结果为:

Enter image description here

重要的是要了解address+1表达式根据address类型给出不同的结果,即+1表示sizeof(addressed data),如sizeof(*address)

因此,如果在您的系统中(对于您的编译器)sizeof(int)sizeof(char)不同(例如,4和1),cp+1ip+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));

输出:

Enter image description here

因此,为了更好地理解,请阅读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的情况下它可能是不同的。