【发布时间】:2015-09-18 05:43:58
【问题描述】:
我们会将 C 中的指针称为数据类型(类型为 void*)还是只是对无符号整数执行的操作,使其值被解释为虚拟内存地址?如果是数据类型,哪些硬件和软件因素会影响其范围?
【问题讨论】:
-
指针确实有类型
我们会将 C 中的指针称为数据类型(类型为 void*)还是只是对无符号整数执行的操作,使其值被解释为虚拟内存地址?如果是数据类型,哪些硬件和软件因素会影响其范围?
【问题讨论】:
我认为您将两件事混合在一起 - 间接运算符和指针变量。
间接运算符 (*) - 间接运算符是一元运算符,可用于获取存储在指针变量引用的内存位置处的值。
指针变量 - 在 C 中,指针是特定类型的变量(例如 int、char、void),用于存储地址并且可以为 null。
指针的大小取决于不同的因素。你可以去下面的链接。他们解释得很好。
What is the size of a pointer? What exactly does it depend on?
【讨论】:
C 认为你的整个计算机是一个庞大的字节数组。显然这不是很有用,但是在这个庞大的字节数组之上的 C 层是类型和这些类型大小的概念。
在您的计算机中创建一块内存。
“指向”名称ptr 位于该块()的开头。
这间接意味着它需要一个与它指向的数据类型相同的类型说明符。
【讨论】:
是的,它们是数据类型。喜欢void *。
intptr_t 整数可以存储除函数指针之外的任何指针。因此,您可以将此类指向数据对象的指针视为特殊整数。 (但请记住整数和指针是不同的类型。)
您的编译器会为您的目标环境生成代码。例如。如果您使用选项-m32 进行编译,那么指针大小可能是32 位。它可以在 32 位架构上运行,其中 CPU 寄存器可以存储 32 位内存地址。虽然 64 位架构可能仍支持 32 位应用程序,但您可以使用选项 -m64 进行编译以受益于更大的指针(可能是 64 位)。
【讨论】:
你问了很多想法。我将尝试尽可能多地引用C standard 来给出官方的想法,然后将其分解为易于理解的内容。
我们会将 C 中的指针称为数据类型(类型为 void *)还是只是对无符号整数执行的操作,使其值被解释为虚拟内存地址?
来自 C 标准:
6.2.5 类型
- 指针类型可以派生自函数类型、对象类型或不完整类型,称为引用类型。指针类型描述了一个对象,其值提供对被引用类型实体的引用。从引用类型 T 派生的指针类型有时称为“指向 T 的指针”。从引用类型构造指针类型称为“指针类型派生”。
6.3.2.3 指针
- 整数可以转换为任何指针类型。除非前面指定,否则结果是实现定义的,可能未正确对齐,可能不指向所引用类型的实体,并且可能是陷阱表示。
- 任何指针类型都可以转换为整数类型。除非前面指定,结果是实现定义的。如果结果不能以整数类型表示,则行为未定义。结果不必在任何整数类型的值范围内。
指针不是数据类型(至少在短语的传统意义上)或整数 - 它是 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 中的指针理论上可以指向的 物理 位置的总数。实际上,由于虚拟内存的工作方式,您作为程序员将看到的范围要有限得多。不过,那是另一天的故事了。
【讨论】:
指针是一个变量,它的值是另一个变量的地址。一般来说,C中的指针可以指向虚拟内存中的任意地址,为NULL。
【讨论】:
指针通常是一个变量,其值是另一个变量的地址,例如内存位置的直接地址。与任何变量或常量一样,您必须先声明一个指针,然后才能使用它来存储任何变量地址。
所有指针的值的实际数据类型,无论是整数、浮点数、字符还是其他,都是一样的,一个长的十六进制数,代表一个内存地址。
例如:int *ip; /* pointer to an integer */
指针值的运行时表示通常是一个原始内存地址(可能通过字内偏移量字段增加),但由于指针的类型包括所指向事物的类型到,包含指针的表达式可以在编译时进行类型检查。指针算法会自动按指向的数据类型的大小进行缩放。
用于 void 指针 (void *) 的 AS 指向未指定类型的对象,因此可以用作“通用”数据指针。由于指向对象的大小和类型未知,因此不能取消引用 void 指针,也不允许对它们进行指针算术运算,尽管它们可以很容易地(并且在许多上下文中隐式地)与任何其他对象指针相互转换输入。
【讨论】: