sizeof(某些指针)是否始终等于4?


227

例如: sizeof(char*)返回4.和一样int*long long*我尝试过的所有内容。有什么例外吗?


51
为什么要记下来?对于任何初学者来说都是好问题。
马丁·约克

2
我怀疑这个问题中还有另一个问题:“ sizeof是什么?” 或可能是“为什么sizeof <任何指针> == 4?4有什么特别之处?”。我对吗?

2
好吧,这取决于您的平台。大多数实现在特定平台上为每种指针共享相同的大小。
phoeagon

Answers:


194

您得到的保证是sizeof(char) == 1。没有其他保证,包括没有保证sizeof(int *) == sizeof(double *)

在实践中,指针在16位系统(如果可以找到)上的大小为2,在32位系统上为4,在64位系统上为8,但是依靠给定的值并没有任何好处尺寸。


96
在24位系统上为3个字节。是的,我已经做了一个。欢迎来到嵌入式设备的世界。
dwj

30
我也在带有20位指针的16位系统上工作。我应该去看看在那种情况下sizeof会返回什么……
Maygarden法官08年

5
@monjardin:IIRC,8086就是这样。有一个16位地址和一个4位段寄存器。我不确定普通的“ NEAR”指针为16位,而声明为“ FAR”的指针则更多,可能为24,尽管我不确定。
rmeador

18
另一个保证是sizeof(char *)== sizeof(void *),因为它们必须具有相同的表示形式(对象[size]和值[与它们的值相关的位的集合]表示形式)
Johannes Schaub-litb

7
由于问题要求例外,因此应注意,非静态成员函数指针的大小通常与普通指针不同,并且还因平台,类型等而异。除+1之外。
John5342

36

即使在普通的x86 32位平台上,您也可以获得各种指针大小,请尝试以下示例:

struct A {};

struct B : virtual public A {};

struct C {};

struct D : public A, public C {};

int main()
{
    cout << "A:" << sizeof(void (A::*)()) << endl;
    cout << "B:" << sizeof(void (B::*)()) << endl;
    cout << "D:" << sizeof(void (D::*)()) << endl;
}

在Visual C ++ 2008下,对于成员函数指针,我得到4、12和8。

Raymond Chen 在这里谈到了这一点


4
指向成员函数的指针确实很痛苦。不幸的是,并非所有的编译器都像Digital Mars C ++编译器那样运行,在所有情况下都返回4。
dalle

gcc 4.72打印全部8个...这在c ++标准中未定义吗?
Gob00st 2012年

2
@ Gob00st:唯一定义的是char为1。其他类型可以是与该编译器相关的任何大小。这些指针类型之间不需要一致性。

好,谢谢。难怪gcc和VC有不同的实现。
Gob00st 2012年

5
@Eclipse是的:char <= short <= int <= long <= long long
Cole Johnson

30

已发布列表的另一个例外。在32位平台上,指针可以占用6 个字节,而不是4个字节:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char far* ptr; // note that this is a far pointer
    printf( "%d\n", sizeof( ptr));
    return EXIT_SUCCESS;
}

如果使用Open Watcom编译该程序并运行它,将得到6,因为它支持的远指针由32位偏移量和16位段值组成


5
不是段,而是选择器-它不是内存地址的一部分,而是LDT或GDT中的索引条目,并且具有一些访问标志
Roee Shenberg 2012年

1
为什么x86在地址空间平坦的情况下存在段和偏移量?
phuclv 2014年

@LưuVĩnhPhúc因为它节省了在通常情况下可以将其编码较短的近指针的空间。
Christopher Creutzig 2014年

1
@ChristopherCreutzig意味着段用于扩展地址空间,例如PAE?
phuclv 2014年

@LưuVĩnhPhúc很长时间以来,我已经完成了对32位任何东西的汇编。我似乎记得的部分是,您可以为指向您所拥有代码附近的指针节省空间。另外,并非所有的32位体系结构(当然也并非全部基于x86)都使用平面内存模型。有关此问题的更多讨论,请参见例如tenouk.com/Bufferoverflowc/Bufferoverflow1a.html,尽管正如我所说,已经有一段时间了,我不能担保任何事情。
Christopher Creutzig 2014年

24

如果要为64位计算机进行编译,则可能为8。


2
虽然通常是这种情况,但不一定是正确的。例如,如果您在字大小为64位的64位计算机上进行编译,则sizeof(char *)可能为1。更不用说在普通计算机中更奇特的指针类型,例如Eclipse和dmityugov写。
卡兹巨龙

@KazDragon ,sizeof(char*)==1?你确定吗?不是size(char)==1
亚伦·麦克戴德

3
@AaronMcDaid我确实的意思是sizeof(char *)。sizeof(char)始终为1。但是,如果您的机器字为64位,并且您的开发环境以CHAR_BITS = 64的方式实现,则指针可能与char容纳在同一空间中,因此将也为1
卡兹龙


1
@KazDragon我正在构建(非常缓慢,当不拖延时)具有16位字且没有字节寻址的机器。尽管它仍然不能运行C。
user253751 '19

17

从技术上讲,C标准仅保证sizeof(char)== 1,其余的取决于实现。但是在现代x86架构(例如Intel / AMD芯片)上,这是可以预见的。

您可能听说过处理器被描述为16位,32位,64位等。这通常意味着处理器将N位用于整数。由于指针存储内存地址,并且内存地址是整数,因此可以有效地告诉您要用于指针的位数。sizeof通常以字节为单位,因此为32位处理器编译的代码将报告指针的大小为4(每字节32位/ 8位),而对于64位处理器的代码将报告指针的大小为8 (64位/每字节8位)。这就是32位处理器4GB RAM限制的来源-如果每个内存地址对应一个字节,要寻址更多内存,您需要大于32位的整数。


“您可能听说过处理器被描述为16位,32位,64位等。这通常意味着处理器将N位用于整数。” ->我有一台64位计算机,但是sizeof(int)是4个字节。如果您的说法是正确的,那怎么可能呢?
Sangeeth Saravanaraj 2012年

6
@SangeethSaravanaraj:为了与32位代码向后兼容,他们决定将int继续为4字节,并要求您通过指定'long'选择使用8字节类型。long实际上是x86-64上的本机字大小。看到这种情况的一种方法是,通常编译器会填充您的结构以使其字对齐(尽管在某些体系结构中字的大小和对齐方式不相关),因此,如果您制作的结构中带有int(32位),并调用sizeof(),如果您取回8,则知道它会将其填充到64位字长。
Joseph Garvin 2012年

@SangeethSaravanaraj:请注意,理论上CPU的本机字长和编译器决定的'int'可以任意不同,只是习惯上将'int'设为x86-64出现之前的本机字长,缓解向后兼容很久了。
约瑟夫·加文2012年

感谢您的解释!:)
Sangeeth Saravanaraj 2012年

7

指针的大小基本上取决于实现它的系统的体系结构。例如,在64位计算机中,32位指针的大小为4字节(32位),而8字节(64位)。机器中的位类型只不过是它可以拥有的内存地址。32位计算机可以具有2^32地址空间,而64位计算机可以具有最高2^64地址空间。因此,指针(指向内存位置的变量)应该能够指向2^32 for 32 bit and 2^64 for 64 bit机器拥有的任何内存地址()。

由于这个原因,我们看到指针的大小在32位计算机中为4字节,在64位计算机中为8字节。


6

除了16/32/64位差异外,甚至可能会发生更奇怪的事情。

曾经有一些机器,其中sizeof(int *)将是一个值,可能是4,但是sizeof(char *)更大。自然寻址字而不是字节的机器必须“增强”字符指针以指定您真正想要的字的哪一部分,以正确实现C / C ++标准。

现在这已经非常不寻常了,因为硬件设计人员已经了解了字节寻址能力的价值。


4
用于Cray矢量机(例如T90)的C编译器执行类似的操作。硬件地址为8字节,指向8字节字。void*char*用软件进行处理,并用一个3位的字内的偏移被增强-但是,因为没有实际上是一个64位的地址空间时,存储在高位64位的3个比特的偏移字。因此,char*int*的大小相同,但是内部表示形式有所不同-并且假定指针“真正”只是整数的代码可能会严重失败。
基思·汤普森

5

大多数低调微控制器都使用8位和16位指针。这意味着每台洗衣机,微型冰箱,冰箱,老式电视,甚至是汽车。

您可以说这些与现实世界的编程无关。但是,这是一个真实的示例:具有1-2-4k内存(取决于芯片)和2个字节指针的Arduino。

它是最新的,便宜的,适合所有人使用,值得编写。


4

除了人们对64位(或其他任何系统)所说的以外,还有其他类型的指针,而不是指向对象的指针。

指向成员的指针几乎可以是任何大小,具体取决于编译器如何实现它们:它们甚至不一定都具有相同的大小。尝试指向POD类的成员的指针,然后尝试从具有多个基类的基类之一继承的成员指针。真有趣


3

我记得,它是基于内存地址的大小。因此,在具有32位地址方案的系统上,sizeof将返回4,因为这是4个字节。


4
没有这样的要求。甚至没有要求sizeof(unsigned int)== sizeof(signed int)。根据定义,指向int的指针的大小始终为sizeof(int *),为char sizeof(char *)等。依赖于任何其他假设对于可移植性是个坏主意。
Mihai Limbășan

啊,我明白了。谢谢(你的)信息。
Will Mc

1
如果CHAR_BIT为16,仍可以返回2。sizeof()以字符数(而非八位字节)为单位。
MSalters 2009年

5
@Mihai:在C ++中sizeof (unsigned int) == sizeof (signed int),此要求位于3.9.1 / 3中。“对于每个整数类型签署的标准的,存在一个对应的(但不同)的标准的无符号整数类型:unsigned charunsigned short intunsigned intunsigned long int,和unsigned long long int其中的每一个占据存储相同量的并具有相同的对齐要求与相应的整数类型签署
Ben Voigt

3

通常,在不同平台上进行编译时,sizeof(几乎任何东西)都会改变。在32位平台上,指针的大小始终相同。在其他平台(明显的例子是64位)上,这种情况可能会改变。



3

在Windows 32位计算机上的Turbo C编译器中,指针和int的大小为2个字节。

因此,指针的大小是编译器特定的。但通常大多数编译器都实现为在32位中支持4字节指针变量,在64位计算机中支持8字节指针变量。

因此指针的大小在所有机器上都不相同。


2

指针大小为4字节的原因是因为您正在编译32位体系结构。正如FryGuy指出的那样,在64位架构上,您会看到8。


2

Win64(Cygwin GCC 5.4)中,让我们看下面的示例:

首先,测试以下结构:

struct list_node{
    int a;
    list_node* prev;
    list_node* next;
};

struct test_struc{
    char a, b;
};

测试代码如下:

std::cout<<"sizeof(int):            "<<sizeof(int)<<std::endl;
std::cout<<"sizeof(int*):           "<<sizeof(int*)<<std::endl;
std::cout<<std::endl;

std::cout<<"sizeof(double):         "<<sizeof(double)<<std::endl;
std::cout<<"sizeof(double*):        "<<sizeof(double*)<<std::endl;
std::cout<<std::endl;

std::cout<<"sizeof(list_node):      "<<sizeof(list_node)<<std::endl;
std::cout<<"sizeof(list_node*):     "<<sizeof(list_node*)<<std::endl;
std::cout<<std::endl;

std::cout<<"sizeof(test_struc):     "<<sizeof(test_struc)<<std::endl;
std::cout<<"sizeof(test_struc*):    "<<sizeof(test_struc*)<<std::endl;    

输出如下:

sizeof(int):            4
sizeof(int*):           8

sizeof(double):         8
sizeof(double*):        8

sizeof(list_node):      24
sizeof(list_node*):     8

sizeof(test_struc):     2
sizeof(test_struc*):    8

您可以看到64位sizeof(pointer)8


1

指针只是地址的容器。在32位计算机上,您的地址范围是32位,因此指针将始终为4个字节。在64位计算机上,如果您的地址范围为64位,则指针将为8个字节。


1
在32位计算机的32位字节,的sizeof(字符*)可以是1
罗伯特Gamble的

“ ...具有32位字节”。我不知道这样的事情存在。
Ed S.

1
在32位鸭子上,sizeof(char *)返回PI
Adriano Varoli Piazza'Dec

0

出于完整性和历史性的考虑,在64位世界中,关于长类型和长长类型的大小存在不同的平台约定,分别称为LLP64和LP64,主要是在Unix类型的系统和Windows之间。名为ILP64的旧标准也将int = 64位宽。

Microsoft维护LLP64,其中longlong = 64位宽,但long保持在32位,以便于移植。

Type           ILP64   LP64   LLP64
char              8      8       8
short            16     16      16
int              64     32      32
long             64     64      32
long long        64     64      64
pointer          64     64      64

资料来源:https : //stackoverflow.com/a/384672/48026

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.