【问题标题】:Why we need float pointer or integer pointer to point float variable or integer variable respectively?为什么我们需要浮点指针或整数指针分别指向浮点变量或整数变量?
【发布时间】:2019-01-23 10:36:20
【问题描述】:

我对指针的了解是,它用于指向特定的位置(内存地址),那么为什么我们甚至需要指针的数据类型与我们试图指向的变量的数据类型相同。 假设我创建了一个整数变量,那么我必须创建一个指向整数的指针来指向它。那么为什么我不能创建一个 void 指针或浮点指针来指向存储在该整数变量中的值! 我错过了一些指针的概念吗?

【问题讨论】:

  • floatinteger 具有不同的表示形式,因此需要 w.r.t 的类型。到指针。您可以有一个 void 指针,但您必须在取消引用之前将指针转换为正确的指针类型。使用 void 指针,您不知道值代表什么
  • 除非你能从指针的类型中分辨出来,否则你怎么知道指针指向什么?我怀疑您总体上缺少类型的要点。
  • 阅读动态类型语言与静态类型语言。 C 和 C++ 属于后者。
  • 只保留类型信息。如果你把你的类型扔掉(void*),没有人知道指针指向什么。你可以看到它指向哪个地址,但是编译器不知道你指向的是什么类型的数据。
  • C++ 是一种强类型语言。如果你想要一个指向某个东西的指针,你通常需要一个该类型的指针来指向它。

标签: c++ c pointers


【解决方案1】:

那么为什么我不能创建一个 void 指针 [...] 来指向存储在该整数变量中的值

你可以这样做,没问题:

int x = 10;
double y = 0.4;
void* v = &x;
v = &y;

但是现在想象一个这样的函数:

void print(void* value)

这个函数如何知道如何处理指针位置的内存?是整数吗?还是浮点数? float 还是 double?也许它是一个巨大的struct 或一组值?您必须知道这一点才能正确取消引用指针(即读取内存),因此只有为指向不同类型的指针设置不同的指针类型才有意义:

void print(int* value)

这个函数知道指针指向int,所以它可以愉快地取消引用它以获得int值。

【讨论】:

    【解决方案2】:

    在处理数组时,指针类型也很重要,因为数组和指针是可以互换的。当你增加一个指针(这是索引所做的)时,你需要知道类型有多大(int、long、结构、类)才能访问下一项。

    arr[5] == *(arr+5) 但是5是什么?这是由类型决定的。

    【讨论】:

    • 指针和数组不可互换。据我所知,数组可能会衰减为指针。
    • 如果您检查幕后发生的事情,数组是使用指针算法实现的。任何有数组的地方,都可以用指针替换它,因此在这方面它们是可以互换的。也许这就是您所说的“指针衰减”的意思?
    • @kbserson 这不是真的。指针和数组的行为不同。试试这个:int arr[10]; int* ptr; cout << sizeof(arr) << endl; cout << sizeof(ptr) << endl; 第一个输出是(在我的系统上)40,第二个是 8。这只是一种情况。还有更多。如果将数组传递给函数,它会衰减为指针。这就是我所说的数组衰减。所以在传递给一个函数之后,两者都会输出 8。或者尝试将一个数组分配给一个整数指针。这也行不通。
    • 正确,它们的大小不会相同,但可以互换使用。如果您有int arr[10];,您可以使用索引arr[5]=7;*(arr+5)=7; 来引用成员。事实上,因为在引擎盖下它们是相同的,你可以写*(5+arr)=7你也可以写5[arr]=7;
    • @kberson 在引擎盖下它们是相同的 ,它们在引擎盖下“相同” . int a[10] 实际上为 10 个 int 值分配空间 - 用于存储 10 个 int 值的内存实际存在int *ptr 创建一个指向 int 值的指针,该指针中的值可能有效也可能无效。创建指针不会创建任何空间来存储实际对象。数组实际上一系列对象本身。有很大的不同。
    【解决方案3】:

    你是对的。虽然intfloat是不同的类型,但它们的指针int*float*应该没有区别。在一般中,情况就是这样。但是,intfloat 之间的二进制表示是不同的。因此,使用float* 指针访问int 会导致从RAM 中读取垃圾。

    此外,您的机器上拥有的不是一般情况,而是取决于硬件和实现。

    例如floatint 变量通常为 32 位长。但是,有些系统int 只有 16 位。如果您尝试从int* 指针读取float,现在会发生什么? (或者,即使两者都是 32 位的,如果您尝试从 char* 读取 float 会发生什么?)

    【讨论】:

    • Therefore accessing an int with a float* pointer leads to garbage being read from the RAM. 不仅如此,它还违反了严格的别名规则 ==> 未定义的行为!相比之下,char* 可能别名 int*,所以你的最后一个例子严格来说没什么大不了的,只要你不占用内存
    • @Pi 真。为了简单起见,我不想解释未定义的行为。
    【解决方案4】:

    在不知道您正在处理哪种数据对象的情况下,内存访问不起作用。

    想象一些简单的任务:

    int a, b=10;
    float f;
    a = b;  // same type => Just copy the integer
    f = b;  // wrong type => Convert to float.
    

    这很好用,因为编译器知道这两个变量都具有某种类型、大小和表示形式。如果类型不匹配,则应用适当的转换。

    现在与类型指针相同:

    int    a = 10;
    float  f;
    int   *pa;
    float *pf;
    
    f = a;   // Type conversion to float applied
    *pa = a; // Just copy
    *pf = a; // Type conversion
    

    如果你不知道指针指向的内存位置,编译器如何知道是否需要转换? 或者如果需要一些整数传播,或者整数是否被截断为更短的类型?

    如果您想使用指针来寻址数组的元素,更多的问题将在拐角处等待。没有类型,指针算术将无法运行。

    类型是必不可少的。对于变量和指针。

    【讨论】:

      【解决方案5】:

      Max Langhof 回答的一个小补充:

      重要的是要认识到,变量最终被简单地存储为一系列位(二进制数字),例如01010101 00011101 11100010 11110000。你的程序怎么知道这“意味着”什么?它可以是一个整数(在现代架构中通常是 4 个字节),也可以是一个浮点值。对于所涉及的内存,这没有什么区别,但是对于您的代码,影响可能是巨大的。因此,如果您引用此内存位置(使用指针),您将需要指定应如何将那里的字节转换为十进制(或其他)值。

      【讨论】:

        【解决方案6】:

        指针算术是主要原因 - 如果p 指向T 类型的对象,那么p+1 指向该类型的下一个对象。如果p指向一个4字节的int,那么p+1指向后面的4字节int。如果p 指向一个128 字节的struct,那么p+1 指向下面的128 字节结构。如果p 指向double 的2 KB 数组,则p+1 指向double 的下一个2 KB 数组,以此类推。

        但这也是出于同样的原因,我们首先有不同的类型 - 在抽象机器级别,我们想要区分不同类型的数据和允许对这些数据进行的操作。指向int 的指针不同于指向double 的指针,因为int 不同于double

        【讨论】:

          猜你喜欢
          • 2016-03-27
          • 1970-01-01
          • 2020-09-19
          • 2014-05-18
          • 1970-01-01
          • 2021-07-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多