【问题标题】:Pointers in C: Data type or operationC中的指针:数据类型或操作
【发布时间】:2015-09-18 05:43:58
【问题描述】:

我们会将 C 中的指针称为数据类型(类型为 void*)还是只是对无符号整数执行的操作,使其值被解释为虚拟内存地址?如果是数据类型,哪些硬件和软件因素会影响其范围?

【问题讨论】:

  • 指针确实有类型

标签: c pointers


【解决方案1】:

我认为您将两件事混合在一起 - 间接运算符和指针变量。

间接运算符 (*) - 间接运算符是一元运算符,可用于获取存储在指针变量引用的内存位置处的值。

指针变量 - 在 C 中,指针是特定类型的变量(例如 int、char、void),用于存储地址并且可以为 null。

指针的大小取决于不同的因素。你可以去下面的链接。他们解释得很好。

What is the size of a pointer? What exactly does it depend on?

【讨论】:

    【解决方案2】:

    C 认为你的整个计算机是一个庞大的字节数组。显然这不是很有用,但是在这个庞大的字节数组之上的 C 层是类型和这些类型大小的概念。

    • 在您的计算机中创建一块内存。

    • “指向”名称ptr 位于该块()的开头。

    这间接意味着它需要一个与它指向的数据类型相同的类型说明符。

    【讨论】:

      【解决方案3】:

      是的,它们是数据类型。喜欢void *

      intptr_t 整数可以存储除函数指针之外的任何指针。因此,您可以将此类指向数据对象的指针视为特殊整数。 (但请记住整数和指针是不同的类型。)

      您的编译器会为您的目标环境生成代码。例如。如果您使用选项-m32 进行编译,那么指针大小可能是32 位。它可以在 32 位架构上运行,其中 CPU 寄存器可以存储 32 位内存地址。虽然 64 位架构可能仍支持 32 位应用程序,但您可以使用选项 -m64 进行编译以受益于更大的指针(可能是 64 位)。

      【讨论】:

        【解决方案4】:

        你问了很多想法。我将尝试尽可能多地引用C standard 来给出官方的想法,然后将其分解为易于理解的内容。


        我们会将 C 中的指针称为数据类型(类型为 void *)还是只是对无符号整数执行的操作,使其值被解释为虚拟内存地址?

        来自 C 标准:

        6.2.5 类型

        1. 指针类型可以派生自函数类型、对象类型或不完整类型,称为引用类型。指针类型描述了一个对象,其值提供对被引用类型实体的引用。从引用类型 T 派生的指针类型有时称为“指向 T 的指针”。从引用类型构造指针类型称为“指针类型派生”。

        6.3.2.3 指针

        1. 整数可以转换为任何指针类型。除非前面指定,否则结果是实现定义的,可能未正确对齐,可能不指向所引用类型的实体,并且可能是陷阱表示。
        2. 任何指针类型都可以转换为整数类型。除非前面指定,结果是实现定义的。如果结果不能以整数类型表示,则行为未定义。结果不必在任何整数类型的值范围内。

        指针不是数据类型(至少在短语的传统意义上)或整数 - 它是 C 程序员表示某个对象位置的方式。虽然我们倾向于将其视为一个数字——即0xf000b3a8——但没有理由必须是一个数字。它只需要标记特定对象的位置。此外,它指向的对象的类型决定了它自己的指针类型。所以类型为“float *”的指针等价于“指向float”的指针。它不是 float 类型 - 它是指针类型。

        举个具体的例子,想想你如何组织你的卧室——也许你有一张床、一张桌子、一套抽屉、一个壁橱和一张床头柜。睡觉前,你拿出一张便条,写下“记住桌上的耳机”。然后你把那个便签贴在你的背包上。该便签是您耳机的指针!它提醒您这些耳机的位置 - 您的办公桌,不是数字。

        我们倾向于将指针视为整数的原因来自 6.3.2.3.5 和 6.3.2.3.6 节。计算机——按照它们目前的设计——不理解“桌子”或“壁橱”的概念。他们只理解数字——所以我们相应地组织它们。因此,C 标准规定整数必须能够转换为指针,反之亦然。


        如果是数据类型,哪些硬件和软件因素会影响其范围?

        同样,指针并不是真正的数据类型——它表示某个对象的位置(该对象又具有指示指针类型的某种类型)。所以我们不能真正谈论指针的 range 本身。我们可以讨论的是可能的内存地址范围(以及指针可能指向的可能位置的范围!)。

        过去,当恐龙在地球上漫游,尼克松在任时(我是个年轻人,我能说什么),英特尔推出了英特尔 8008 微处理器1。这只小狗是世界上第一个 8 位 CPU - 也就是说,它可以对 8 位值执行数学运算。假设 2 的补码表示法,这允许 0 到 28-1(0 到 255)的无符号值和 -27 到 27 的有符号值sup>-1(-128 到 127)。此外,它还有一个外部 14 位地址总线,可以寻址高达 16KB 的内存。这相当于 214 (16384) 个内存位置,每个位置包含 8 位。因此,整个范围是从字节 0 到字节 16383。

        快进到今天。大多数现代台式机和笔记本电脑都在 64 位处理器上运行。这些支持(理论上)264 字节的内存 - 多达 18,446,744,073,709,551,616 个位置。这相当于大约 16 艾字节 - 其中 1 艾字节是 1,000,000 TB。 (It's speculated that Google stores approximately this much data in their datacenters)。然而,目前大多数架构只使用较低的 48 位2

        这些表示 C 中的指针理论上可以指向的 物理 位置的总数。实际上,由于虚拟内存的工作方式,您作为程序员将看到的范围要有限得多。不过,那是另一天的故事了。

        【讨论】:

          【解决方案5】:

          指针是一个变量,它的值是另一个变量的地址。一般来说,C中的指针可以指向虚拟内存中的任意地址,为NULL。

          【讨论】:

          • 指针只能指向存在的对象(或超过这些对象的末尾),或者为空。试图指向其他任何地方会导致标准 C 中未定义的行为。(某些实现可能将其作为扩展提供)
          【解决方案6】:

          指针通常是一个变量,其值是另一个变量的地址,例如内存位置的直接地址。与任何变量或常量一样,您必须先声明一个指针,然后才能使用它来存储任何变量地址。

          所有指针的值的实际数据类型,无论是整数、浮点数、字符还是其他,都是一样的,一个长的十六进制数,代表一个内存地址。

          例如:int *ip; /* pointer to an integer */

          指针值的运行时表示通常是一个原始内存地址(可能通过字内偏移量字段增加),但由于指针的类型包括所指向事物的类型到,包含指针的表达式可以在编译时进行类型检查。指针算法会自动按指向的数据类型的大小进行缩放。

          用于 void 指针 (void *) 的 AS 指向未指定类型的对象,因此可以用作“通用”数据指针。由于指向对象的大小和类型未知,因此不能取消引用 void 指针,也不允许对它们进行指针算术运算,尽管它们可以很容易地(并且在许多上下文中隐式地)与任何其他对象指针相互转换输入。

          See wiki

          【讨论】:

          • 指针的实际数据类型是……该类型的指针。它不是一个数字(更不用说十六进制数,不管它应该是什么意思)
          • 这种“所有指针的值的实际数据类型[...]都相同”一般是错误的,因为可能有系统指向不同的指针对象的类型有不同的实现,例如不同的大小。
          猜你喜欢
          • 2017-09-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-28
          相关资源
          最近更新 更多