为什么我们需要不同的数据类型来表示指针


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

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

您也不需要不同的数据类型,您可以使用void*就可以了,但是您为什么要这样做呢?在C++,这是一种代码气味。

还有类型安全。你知道一个int*指向一个int,这对你有利。

两个原因:

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

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

对于初学者来说,我不知道有哪台机器有指针存储为十六进制;我熟悉的每台机器都用过内部的二进制表示形式。 (对于最后 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;

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

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

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

通过C类型不安全功能:是的,但不是直接的,特别是在最近的编译器和标准中(它们往往更安全,更安全(

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

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

如果您将"变量">

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

一个这样的案例是这样的:考虑语句

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 个字节。这意味着您将在 i 的前四个字节之后读取 4 个不可预测的(随机(字节,这绝对是您不想做的事情。

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

相关内容

  • 没有找到相关文章

最新更新