[英]Why can't we generalize the pointer declaration?
无论指向的数据类型如何,指针的大小都是相同的。那为什么我们需要声明它指向的数据类型?
例如,
int *p; //p will point to an integer data type.
char *p; //p will point to a character
那么,为什么我们不能概括这样的指针声明
pointer p; //where p is an object of pointer class.
TL; DR因为,不同的数据类型在内存中占用不同的大小并且具有不同的对齐要求。
详细说明,指针变量包含指向某种类型数据的地址。 如果没有关联的类型,就无法取消引用指针并获取值 。
换句话说,要访问指针指向的数据,必须知道关联的数据类型。
指针本身的大小与它指向的实际数据几乎没有联系。
存在一个指针, void *
被认为是一个通用指针,但是,你不能取消引用它,因为取消引用的结果会尝试产生一个不完整的类型。 您需要将其强制转换为完整类型,以便能够取消引用或对void指针应用指针算法。
考虑void *
一般指针的原因如下,引用C11
标准,第6.3.2.3章
指向
void
的指针可以转换为指向任何对象类型的指针。 指向任何对象类型的指针可以转换为指向void
的指针,然后再返回; 结果应该等于原始指针。
因此, void *
可以用作可以保存任何指针类型的通用容器 ,但是要对指针进行一些操作(包括数据类型的知识),首先需要将其转换为完整类型。
指针算术。
说明:
int arr[] = {4, 6, 9, 10};
int* x = arr;
*(x+0) = 4
*(x+1) = 6
编译器知道x + 1实际上是x + sizeof(int)而不是1。
要读取第二个元素,编译器必须每次都跳过sizeof(int)。 在不知道实际类型的情况下,您无法取消引用它并正确提取数据。
Plus类型的大小不同,编译器需要知道从指向的内存中读取多少字节。 char将是1个字节,int将超过1个字节。
您可以使用void*
来概括指针。 void*
是指向某个地址的指针,没有任何关联的类型信息。 但是,如果不将这些指针首先强制转换为显式指针类型,则几乎无法使用这些指针。
请考虑以下示例。 它不会编译,因为不可能推断出ptr
指向的“值”。 你甚至不知道该值构成了多少字节。
void print(const void * ptr) {
std::cout << *ptr; // What's the "value" of ptr?
}
void *
指针可以被视为“通用”指针。
但是,它不能被解除引用,因为通用它并不指向任何一种类型的对象。 要实际使用 void *
指针并访问它指向的任何内容,您需要将其强制转换为您正在访问的对象类型。
并且因为它没有指向任何一种类型的对象,所以没有适当的方法对void *
指针执行指针运算。
无论指向的数据类型如何,指针的大小都是相同的。
这不一定是真的 - 指向不同类型的指针可能具有不同的大小和表示:
指向void
的指针应具有与指向字符类型的指针相同的表示和对齐要求。
48)类似地,指向兼容类型的合格或非限定版本的指针应具有相同的表示和对齐要求。
所有指向结构类型的指针都应具有相同的表示和对齐要求。
所有指向union类型的指针都应具有相同的表示和对齐要求。
指向其他类型的指针不需要具有相同的表示或对齐要求 。
C 2011在线草案 ,§6.2.5¶28
指针类型的值表示是实现定义的。 布局兼容类型的指针应具有相同的值表示和对齐要求(3.11)。
C ++ 2014工作草案 ,§3.9.2,¶3
在大多数现代桌面和服务器上它们是相同的,但不要指望它是普遍真实的。
那为什么我们需要声明它指向的数据类型?
指针算法取决于指向类型 - 如果p
指向类型为T
的对象,则p + 1
指向类型为T
的下一个对象。 由于不同类型具有不同的大小,因此您需要知道指向类型以正确计算偏移量。
那么,为什么我们不能概括这样的指针声明
pointer p; //where p is an object of pointer class.
你实际上可以使用void*
。 但结果是在那一点上所有类型(和大小信息)都丢失了。
你必须以某种方式(硬编码类型转换或其他)跟踪它,以使其有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.