8
  1. 基本上指针是一个用于存储内存地址的变量,它总是
    十六进制(内存地址)那么为什么我们需要不同的数据类型来存储地址。
  2. 例如:int *a;我们可以用它来存储浮点地址吗?
4

5 回答 5

12

并非所有指针都(必须是)相同的大小。如果您有一个需要对齐到 10 MB 的大型结构,编译器可以决定它只需要 8 位(而不是通常的 32 或 64 位)来存储您的变量可能位于的所有可能地址。

你也不需要不同的数据类型,你可以void*很好地使用,但你为什么会呢?在 C++ 中,这是一种代码气味。

还有类型安全。你知道一个int*点到一个int,这是你的优势。

于 2013-10-10T09:40:52.343 回答
7

两个原因:

  1. 在某些架构上,指针可能具有不同的格式,具体取决于它们指向的数据的大小。例如,指向的指针char必须能够寻址单个字节,但指向的指针int只需要能够寻址 4 个字节的组。因此后者可以使用包含字节地址除以 4 的格式。

  2. 它允许编译器生成正确的程序。如果您尝试取消引用char指针并将其分配给 a int,它需要知道它应该只从源读取一个字节,并将其扩大到 a 的大小int。如果没有指针类型声明,它将读取比适当更多的字节。

于 2013-10-10T09:44:59.410 回答
3

对于初学者,我不知道指针存储为十六进制的机器。我熟悉的每台机器内部都使用二进制表示。(至少在过去的 30 或 40 年里。IIRC,IBM 1401 到处都使用十进制。)

正如其他人指出的那样,并非所有指针具有相同的大小和表示形式。我曾在char* 比其他数据指针类型更大的机器上工作过,当然,函数指针和数据指针的大小不同曾经很常见。

然而,真正的答案是基于 C 和 C++ 中的类型系统。如果p是指针,它的类型是*p什么?例如,如果我写类似的东西*p + *q,编译器必须知道是使用整数运算还是浮点运算。

至于你的第二个问题:通常,是的,尽管你可能需要reinterpret_cast在某个地方。但是,您唯一可以合法地对您做的事情int*就是将其重新转换为float*; 取消引用它是未定义的行为。

char*和有一些例外unsigned char*。在实践中,如果您知道自己在做什么,就可以摆脱以下问题:

float f;
int* a = reinterpret_cast<int*>( &f );
std::cout << *a << std::endl;

我实际上为某些低级调试或编程做类似的事情;诸如从 a 中提取指数字段之类的事情float。然而,这样的代码极为罕见,而且形式上涉及未定义的行为,因此您必须验证编译器实际做了什么,并可能关闭某些优化。

于 2013-10-10T09:52:49.830 回答
2

因为它提供了有关如何解释指针指向的数据的信息。

例如:int *a;我们可以用它来存储浮点地址吗?

通过 C 类型的不安全特性:是的,但不是直接的,尤其是在最近的编译器和标准中(这往往更安全)

于 2013-10-10T09:42:56.403 回答
1

为什么我们需要不同的数据类型来存储地址

这实际上是一个正确的问题,答案隐藏在其中——为什么我们需要不同的数据类型来存储地址。我们(程序员)需要它。机器不在乎——一个数字和另一个数字一样。

如果您将“变量”视为某些数据的“占位符”,那么编程语言在使用数据本身和使用变量之间存在二分法。有时您只需要数据(例如,您需要打印出来),有时您需要存储这些数据的地址(例如,您可以修改它)。大多数语言都有混淆这两种情况的语法糖,并且在不同的上下文中以不同的方式对待变量标识符。

一个这样的情况是这样的:考虑语句

a = 1;

在这种情况下,编译器查找由“a”标识的变量的地址,并将“1”写入该地址。标识符“a”也可能是一个指针。现在看一个不同的东西:

if (a == 1) ... ;

不是将由“a”标识的变量的地址与某物进行比较,而是将该地址中存储的内容与“1”进行比较。

为了程序员的方便,各种“指针类型”再次存在:基本上是为了减少错误访问数据的错误。看这个例子:

double d;
double* dp;
int i;
int* ip;

默认情况下,C 对此非常放松,您通常可以这样做:

dp = ip;

或者

dp = &i;

... 但!sizeof(i)==4 和 sizeof(d)==8,因此如果取消引用 dp 指针,您将尝试从仅包含 4 的变量 (i) 中读取 8 个字节。这意味着您将读取 4 个不可预测的i 的前四个字节之后的(随机)字节,这绝对是您不想做的事情。

同样,所有这些都是为了我们的方便。机器不在乎。对于 CPU,这两个指针的外观和行为完全相同。

于 2013-10-10T10:11:13.020 回答