13

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

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

4

7 回答 7

18

有几个原因:

  • 并非所有地址都是平等的;特别是,在非冯诺依曼(例如哈佛)体系结构中,指向代码内存(通常存储常量)的指针和指向数据内存的指针是不同的。
  • 您需要知道基础类型才能正确执行访问。例如,读或写 achar不同于读或写 a double
  • 您需要额外的信息来执行指针运算。

请注意,在 C 语言中有一种指针类型表示“只是一个指针”,称为void*. 您可以使用此指针来传输内存中的地址,但您需要将其转换为有用的东西以便在 . 指向的内存中执行操作void*

于 2012-09-21T12:45:51.350 回答
5

指针不只是int. 它们隐含地具有语义。

这里有几个例子:

  • p->memberp仅当您知道类型指向什么时才有意义。

  • p = p+1;根据您指向的对象的大小,行为会有所不同(从某种意义上说,“p”实际上是递增的,当被视为无符号整数时,它所指向的类型的大小)。

于 2012-09-21T12:46:56.730 回答
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+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

注意:在这种情况下,具体的地址值并不重要。唯一的区别是指针持有的变量类型,这显然很重要。

更新:

顺便说一句,地址(指针)算术不受+1or的限制++,可以举出很多例子,比如:

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));

带输出:

在此处输入图像描述

因此,为了更好地理解,请阅读教程

于 2017-02-08T08:01:25.413 回答
2

因为您假设“地址始终是 int 类型”是错误的。

完全有可能创建一个计算机体系结构,例如,由于某种原因,指向字符的指针大于指向单词的指针。C 会处理这个问题。

此外,当然,可以取消引用指针,并且当您这样做时,编译器需要知道您希望在相关地址中找到的数据类型。否则,它无法生成正确的指令来处理该数据。

考虑:

char *x = malloc(sizeof *x);
*x = 0;

double *y = malloc(sizeof *y);
*y = 0;

这两个片段将写入完全不同的内存量(或者如果分配失败,则爆炸,暂时不要介意),但实际的文字常量(0类型为int)在两种情况下都是相同的。关于指针类型的信息允许编译器生成正确的代码。

于 2012-09-21T12:42:13.293 回答
2

您可以非常轻松地在 C 中使用无类型指针——您只需将void *其用于所有指针。尽管出于两个我能想到的原因,这将是相当愚蠢的。

首先,通过指定类型中指向的数据,编译器可以避免许多愚蠢的错误、拼写错误或其他错误。相反,如果您剥夺了编译器的这些信息,那么您肯定会花费大量时间来调试本不应该成为问题的事情。

此外,您可能使用过“指针算法”。例如,int *pInt = &someInt; pInt++;-- 将指针前进到内存中的下一个整数;无论类型如何,这都有效,并前进到正确的地址,但只有在编译器知道所指向内容的大小时它才能工作。

于 2012-09-21T12:45:43.263 回答
0

它主要适用于那些在您之后阅读代码的人,以便他们知道该地址存储了什么。此外,如果您在代码中执行任何指针运算,编译器需要知道如果您执行 pSomething++ 之类的操作,他应该前进多少,这是由指针的类型给出的,因为您的数据类型的大小是编译前已知。

于 2012-09-21T12:45:55.313 回答
0

因为指针的类型告诉编译器一次可以执行多少字节的操作。

示例:在 的情况下char,只有一个字节。如果是两个字节的 int,它可能会有所不同。

于 2012-09-21T12:46:30.263 回答