指针的大小是相同的,与它指向的数据类型无关。那为什么我们需要声明它指向的数据类型?
例如,
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.
答案 0 :(得分:13)
TL; DR 因为,不同的数据类型在内存中占用不同的大小,并且具有不同的对齐要求。
详细说明,指针变量包含指向某种类型数据的地址。如果没有关联的类型,就无法取消引用指针并获取值。
换句话说,要访问指针指向的数据,必须知道相关的数据类型。
指针本身的大小与它指向的实际数据几乎没有联系。
存在一个指针,void *
被认为是泛型指针,但是,您不能取消引用它,因为取消引用的结果会尝试生成不完整的类型。您需要将其强制转换为完整类型,以便能够取消引用或对void指针应用指针算法。
考虑void *
泛型指针的原因如下,引用C11
标准,第3.6.2.3章
指向
void
的指针可以转换为指向任何对象类型的指针。指向的指针 任何对象类型都可以转换为指向void
并再次返回的指针;结果应该 比较等于原始指针。
因此,void *
可以用作通用容器,它可以保存任何指针类型,但是对指针进行一些操作(包括数据类型的知识) ,你需要先把它变成一个完整的类型。
答案 1 :(得分:6)
指针算法。
说明:
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个字节。
答案 2 :(得分:6)
你可以使用void*
来推广指针。 void*
是指向某个地址的指针,没有任何关联的类型信息。但是,如果不将这些指针首先转换为显式指针类型,则几乎无法使用这些指针。
考虑以下示例。它不会编译,因为不可能推导出ptr
指向的“值”。你甚至不知道该值构成了多少字节。
void print(const void * ptr) {
std::cout << *ptr; // What's the "value" of ptr?
}
答案 3 :(得分:2)
void *
指针可以被视为“通用”指针。
但是,它不能被解除引用,因为通用它并不指向任何一种类型的对象。要实际使用一个void *
指针并访问它指向的内容,您需要将其转换为您正在访问的对象类型。
由于它没有指向任何一种类型的对象,因此没有正确的方法在void *
指针上执行指针算法。
答案 4 :(得分:1)
无论指向的数据类型如何,指针的大小都是相同的。
这不一定正确 - 指向不同类型的指针可能具有不同的大小和表示:
指向void
的指针应具有与a相同的表示和对齐要求
指向字符类型的指针。 48)同样,指向合格或非限定版本的指针
兼容类型应具有相同的表示和对齐要求。所有
指向结构类型的指针应具有相同的表示和对齐要求
彼此相同。所有指向联合类型的指针都应具有相同的表示形式
对齐要求彼此。 指向其他类型的指针不必相同
表示或对齐要求。
C 2011 Online Draft,§6.2.5¶28
指针类型的值表示 是实现定义的。布局兼容类型的指针应具有相同的值表示和 对齐要求(3.11)。
C++ 2014 Working Draft,§3.9.2,¶3
在大多数现代桌面和服务器上,它们是相同的,但不要指望它普遍适用。
那么为什么我们需要声明它指向的数据类型?
指针算法取决于指向的类型 - 如果p
指向类型为T
的对象,则p + 1
指向类型为T
的下一个对象。由于不同类型具有不同的大小,因此您需要知道指向类型以正确计算偏移量。
答案 5 :(得分:0)
然后,为什么我们不能概括像这样的指针声明
pointer p; //where p is an object of pointer class.
您实际上可以使用void*
。但结果是在那一点上所有类型(和大小信息)都丢失了。
你必须以某种方式(硬编码类型演员或其他)跟踪这些,以使其有用。