Is the sizeof(some pointer) always equal to four?
Asked Answered
N

17

257

For example: sizeof(char*) returns 4. As does int*, long long*, everything that I've tried. Are there any exceptions to this?

Nardone answered 29/12, 2008 at 23:3 Comment(4)
Why mark this down? Good question for any beginner.Luehrmann
I suspect that another question is hiding in this one: "What is sizeof?" or may be "Why is sizeof <any pointer> == 4? What's so special about 4?". Am I right?Confirmed
Well, it depends on your platform. Most implementations share a same size for every kind of pointer on a specific platform.Dearden
Please ask for either C or C++, not for both in the same question. This are 2 different languages. Only include both when you ask about the differences or similarities between them.Granado
F
220

The guarantee you get is that sizeof(char) == 1. There are no other guarantees, including no guarantee that sizeof(int *) == sizeof(double *).

In practice, pointers will be size 2 on a 16-bit system (if you can find one), 4 on a 32-bit system, and 8 on a 64-bit system, but there's nothing to be gained in relying on a given size.

Frig answered 29/12, 2008 at 23:11 Comment(25)
And 3 bytes on a 24-bit system. Yes, I've worked on one. Welcome to the world of embedded devices.Brisling
I've worked on 16-bit systems with 20-bit pointers as well. I should go see what sizeof returns in that case...Viridis
@monjardin: IIRC, the 8086 was like that. There was a 16 bit address and a 4 bit segment register. I believe a normal "NEAR" pointer was 16 bits and a pointer declared as "FAR" was more, probably 24, though I'm not sure.Mudskipper
I worked on a (32-bit) system where the 'char *' to something had a different bit representation to the 'anthing_else *' to the same memory location. You learned to ensure that 'malloc()' was declared (because in those days of yore, malloc() returned 'char *' and not 'void *'). Beware!Medick
(cont): The size of the pointers was the same in all cases; it was just the bit pattern that differed. I've not seen systems where pointers to different data types have different sizes. I have seen systems where code (function) pointers are different sizes from data pointers.Medick
In certain memory models, a pointer on an 8086 was 32 bits. A 16-bit segment and a 16-bit offset. The processor would combine these by shifting the segment 4 bits to the left and adding the offset, resulting in a 20-bit address. Two different pointers could point to the same physical address! fun!Scrip
16 bit systems are easy to find. Any code that runs in THUMB mode on an ARM chip.Bonheur
Sorry, @ApplePieIsGood: ARM THUMB code is still 32-bit code. It's just a technique to compress the instruction size from 32-bits to 16-bits, but the address space is still the same.Jermayne
another guarantee is that sizeof(char*) == sizeof(void*) , because they have to have the same representationss (object [size] and value [set of bits relevant for their value] representation)Leucoma
Ferruccio: It's not old. My Core 2 Quad processor also supports real mode ;-PDeathbed
Of course if you have a pointer to a member function of a class that uses multiple or virtual inheritance, then you'll likely get completely different pointer sizes.Diva
itanium sometimes uses 2word (2 pointers) for representing 1 function pointer.Calico
There are other guarantees such as sizeof(int) <= sizeof(long). They could be the same or long could be massively larger than int, but it'll never be smaller.Sumach
@JudgeMaygarden sounds like the 16-bit Real WorldConductance
Since the question asks for exceptions it should be noted that non-static member function pointers are often a different size to normal pointers and also vary by platform, type, etc. Other than that +1.Mme
8 and 16 bit is everywhere. Washing mashines, fridges, micros, remote controllers, car keys.Evert
There's also a guarantee that all pointers to structs have the same size and layout, and all pointers to unions have the same size and representation. And pointers to signed/unsigned quantities. And pointers to plain/const/volatile objects.Berserk
@gnasher729: I know there are guarantees about casting pointers, but where is there a guarantee about the size and representation?Fiertz
@JohannesSchaub-litb: where does the standard says that sizeof(char*) == sizeof(void*) ?Skimp
Does it mean that, no matter what the data type is, address is address and that's what the pointer stores, for that reason it must be the same size?Mulvey
@JudgeMaygarden So what did it say?Cacciatore
@chux-ReinstateMonica: N1570 6.2.5 paragraph 28 specifies that in C, "A pointer to void shall have the same representation and alignment requirements as a pointer to a character type". I think that would imply that they are the same size.Gemmiparous
@Gemmiparous Agree. In the last 3 yr, I have learned of that spec. I suspect the allowed variation of object pointer size amongst int, FP, Struct, char is a feature of the past - I know of no now variation. OTOH, function pointers and object pointer vary.Heyduck
How can be that sizeof int* != sizeof double*? Does it mean that int or double located in the heap cannot have some bigger size addresses? For example if sizeof int* is 4 and sizeof double* is 8 then doubles can have large 8-byte addresses in the heap, while ints are capped only to have 4-byte addresses in the heap? And what's about user-defined types? Is it also be possible that sizeof class1* != sizeof class2*?Frazzled
It should be pointed out that sizeof(char) == 1 is a definition. So, sizeof(int) == 4 means that an int is four times as big as a char even if a char is, say, 16 bits.Employee
D
39

Even on a plain x86 32 bit platform, you can get a variety of pointer sizes, try this out for an example:

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;
}

Under Visual C++ 2008, I get 4, 12 and 8 for the sizes of the pointers-to-member-function.

Raymond Chen talked about this here.

Diva answered 13/1, 2009 at 22:53 Comment(7)
Pointers to member functions are a real pain. It is unfortunate that not all compilers does it like the Digital Mars C++ compiler, which return 4 in all cases.Kirmess
gcc 4.72 print all 8 ... Is this undefined in c++ standard ?Golgi
@Gob00st: The only thing that's defined is that char is 1. Other types can be whatever size is relevant to that compiler. There's no requirement for consistency between these pointer types.Diva
ok thanks. Then no wonder gcc & VC have different implementation .Golgi
@Diva yes there is: char <= short <= int <= long <= long longConductance
@ColeJohnson where is the relation coming from? Should the first <= be <, namely char < short?Asci
@Asci That relation comes from the standard. It does not say anything about their bit widths, but it does guarantee that all sizes are bigger or equal to the previous. char is always smaller than or equal to short, ..., int is always smaller than or equal to long, etc. I don’t have the standard on hand, so I can’t give a reference ATM.Conductance
C
33

Just another exception to the already posted list. On 32-bit platforms, pointers can take 6, not 4, bytes:

#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;
}

If you compile this program with Open Watcom and run it, you'll get 6, because far pointers that it supports consist of 32-bit offset and 16-bit segment values

Climax answered 30/12, 2008 at 10:58 Comment(6)
Not segment, but selector rather - it isn't a part of the memory address, but an index entry in the LDT or GDT and has some access flagsRentschler
Why are there segments and offsets in x86 while the address space is flat?Vanderhoek
@LưuVĩnhPhúc Because it saves space for the very common case of near pointers, which can be encoded shorter.Billiards
@ChristopherCreutzig that means the segments are used for extending address space like PAE?Vanderhoek
@LưuVĩnhPhúc It’s been a long time that I’ve done assembly on anything 32 bit. The part I seem to remember is that you can save space for pointers pointing near to the code you have. Also, not all 32 bit architectures – certainly not all based on the x86 – use a flat memory model. See, e.g., tenouk.com/Bufferoverflowc/Bufferoverflow1a.html for some more discussion around this, although, as I said, it’s been a while and I cannot vouch for anything.Billiards
@Lưu Vĩnh Phúc The segmented architecture introduced with the 8088 and 8086 was predicated on the assumption that memory prices were high, so costs could be saved by keeping everything in 64K segments. It was a major headache to those of us programming low level code in that environment. It is rarely used now, but is still present in intel CPU's for the masochists among us.Shan
J
24

if you are compiling for a 64-bit machine, then it may be 8.

Jonell answered 29/12, 2008 at 23:4 Comment(8)
While this is usually the case, it is not necessarily true. For example, if you're compiling on a 64-bit machine where the word size is 64-bits, then sizeof(char*) will probably be 1. Not to mention the more exotic pointer types in even common machines, as Eclipse and dmityugov write.Lekishalela
@KazDragon, sizeof(char*)==1 ? Are you sure? Don't you mean size(char)==1?Waziristan
@AaronMcDaid I did indeed mean sizeof(char*). sizeof(char) is always 1. But if your machine word is 64-bits, and your development environment is implemented in such a way that CHAR_BITS=64, then it's possible that a pointer fits in the same space as a char and will hence also be 1.Lekishalela
it's not true in x32-abi sites.google.com/site/x32abiVanderhoek
Just curious, @KazDragon can you give an example of a machine where CHAR_BITS=64?Interlope
@Interlope No, but I could build one if I so chose.Lekishalela
@KazDragon I am building (very slowly, when not procrastinating) a machine with 16-bit words and no byte addressing. Although it can't run C anyway.Earthquake
@user253751: There are of course a number of off-the-shelf DSP chips like that.Execration
T
18

Technically speaking, the C standard only guarantees that sizeof(char) == 1, and the rest is up to the implementation. But on modern x86 architectures (e.g. Intel/AMD chips) it's fairly predictable.

You've probably heard processors described as being 16-bit, 32-bit, 64-bit, etc. This usually means that the processor uses N-bits for integers. Since pointers store memory addresses, and memory addresses are integers, this effectively tells you how many bits are going to be used for pointers. sizeof is usually measured in bytes, so code compiled for 32-bit processors will report the size of pointers to be 4 (32 bits / 8 bits per byte), and code for 64-bit processors will report the size of pointers to be 8 (64 bits / 8 bits per byte). This is where the limitation of 4GB of RAM for 32-bit processors comes from -- if each memory address corresponds to a byte, to address more memory you need integers larger than 32-bits.

Tenderhearted answered 31/12, 2008 at 4:19 Comment(3)
"You've probably heard processors described as being 16-bit, 32-bit, 64-bit, etc. This usually means that the processor uses N-bits for integers." -> I'm having a 64-bit machine but the sizeof(int) is 4 bytes. If your statement is true, how could this be possible?!Doings
@SangeethSaravanaraj: For backwards compatibility with 32-bit code, they decided to have int continue to be 4 bytes and require you to opt-in to using the 8 byte type by specifying 'long'. long is actually the native word size on x86-64. One way to see this is that typically compilers will pad your structs to make them word aligned (though there may be architectures where word size and alignment are unrelated), so if you make a struct with an int (32-bits) in it, and call sizeof() on it, if you get back 8 you know it's padding them to 64-bit word size.Tenderhearted
@SangeethSaravanaraj: Note that theoretically the native word size of the CPU and what the compiler decides 'int' is can be arbitrarily different, it's just it was convention for 'int' to be the native word size before x86-64 came around, where it's long to ease backwards compat.Tenderhearted
P
10

The size of the pointer basically depends on the architecture of the system in which it is implemented. For example the size of a pointer in 32 bit is 4 bytes (32 bit ) and 8 bytes(64 bit ) in a 64 bit machines. The bit types in a machine are nothing but memory address, that it can have. 32 bit machines can have 2^32 address space and 64 bit machines can have upto 2^64 address spaces. So a pointer (variable which points to a memory location) should be able to point to any of the memory address (2^32 for 32 bit and 2^64 for 64 bit) that a machines holds.

Because of this reason we see the size of a pointer to be 4 bytes in 32 bit machine and 8 bytes in a 64 bit machine.

Phlegm answered 5/6, 2015 at 3:0 Comment(0)
P
6

In addition to the 16/32/64 bit differences even odder things can occur.

There have been machines where sizeof(int *) will be one value, probably 4 but where sizeof(char *) is larger. Machines that naturally address words instead of bytes have to "augment" character pointers to specify what portion of the word you really want in order to properly implement the C/C++ standard.

This is now very unusual as hardware designers have learned the value of byte addressability.

Portauprince answered 29/12, 2008 at 23:50 Comment(1)
The C compiler for Cray vector machines, such as the T90, do something similar. Hardware addresses are 8 bytes, and point to 8-byte words. void* and char* are handled in software, and are augmented with a 3-bit offset within the word -- but since there isn't actually a 64-bit address space, the offset is stored in the high-order 3 bits of the 64-bit word. So char* and int* are the same size, but have different internal representations -- and code that assumes that pointers are "really" just integers can fail badly.Rafaello
E
6

8 bit and 16 bit pointers are used in most low profile microcontrollers. That means every washing machine, micro, fridge, older TVs, and even cars.

You could say these have nothing to do with real world programming. But here is one real world example: Arduino with 1-2-4k ram (depending on chip) with 2 byte pointers.

It's recent, cheap, accessible for everyone and worths coding for.

Evert answered 16/7, 2013 at 20:23 Comment(0)
T
4

In addition to what people have said about 64-bit (or whatever) systems, there are other kinds of pointer than pointer-to-object.

A pointer-to-member might be almost any size, depending how they're implemented by your compiler: they aren't necessarily even all the same size. Try a pointer-to-member of a POD class, and then a pointer-to-member inherited from one of the base classes of a class with multiple bases. What fun.

Tali answered 31/12, 2008 at 1:39 Comment(0)
S
4

In Win64 (Cygwin GCC 5.4), let's see the below example:

First, test the following struct:

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

struct test_struc{
    char a, b;
};

The test code is below:

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;    

The output is below:

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

You can see that in 64-bit, sizeof(pointer) is 8.

Skaw answered 8/6, 2018 at 1:10 Comment(0)
L
3

From what I recall, it's based on the size of a memory address. So on a system with a 32-bit address scheme, sizeof will return 4, since that's 4 bytes.

Lump answered 29/12, 2008 at 23:4 Comment(3)
There is no such requirement. There is not even a requirement that sizeof(unsigned int) == sizeof(signed int). The size of a pointer to an int will always be, by definition, sizeof(int *), to a char sizeof(char *) etc. Relying on any other assumption is a bad idea for portability.Castro
Could still return 2, if CHAR_BIT is 16. sizeof() counts in number of chars, not octets.Bioastronautics
@Mihai: In C++ sizeof (unsigned int) == sizeof (signed int), this requirement is found in 3.9.1/3. "For each of the standard signed integer types, there exists a corresponding (but different) standard unsigned integer type: unsigned char, unsigned short int, unsigned int, unsigned long int, and unsigned long long int, each of which occupies the same amount of storage and has the same alignment requirements as the corresponding signed integer type"Execration
K
3

In general, sizeof(pretty much anything) will change when you compile on different platforms. On a 32 bit platform, pointers are always the same size. On other platforms (64 bit being the obvious example) this can change.

Kirovabad answered 29/12, 2008 at 23:6 Comment(0)
V
3

No, the size of a pointer may vary depending on the architecture. There are numerous exceptions.

Viridis answered 29/12, 2008 at 23:17 Comment(0)
C
3

Size of pointer and int is 2 bytes in Turbo C compiler on windows 32 bit machine.

So size of pointer is compiler specific. But generally most of the compilers are implemented to support 4 byte pointer variable in 32 bit and 8 byte pointer variable in 64 bit machine).

So size of pointer is not same in all machines.

Catcher answered 14/7, 2014 at 19:4 Comment(0)
P
2

The reason the size of your pointer is 4 bytes is because you are compiling for a 32-bit architecture. As FryGuy pointed out, on a 64-bit architecture you would see 8.

Pilgrimage answered 29/12, 2008 at 23:5 Comment(0)
B
1

A pointer is just a container for an address. On a 32 bit machine, your address range is 32 bits, so a pointer will always be 4 bytes. On a 64 bit machine were you have an address range of 64 bits, a pointer will be 8 bytes.

Barragan answered 29/12, 2008 at 23:8 Comment(3)
On a 32-bit machine with 32-bit bytes, sizeof(char *) could be 1.Pryor
"...with 32-bit bytes". I didn't know such things existed...fancy that.Barragan
On a 32 bit duck, sizeof(char *) returns PIKroon
H
0

Just for completeness and historic interest, in the 64bit world there were different platform conventions on the sizes of long and long long types, named LLP64 and LP64, mainly between Unix-type systems and Windows. An old standard named ILP64 also made int = 64-bit wide.

Microsoft maintained LLP64 where longlong = 64 bit wide, but long remained at 32, for easier porting.

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

Source: https://mcmap.net/q/49255/-what-is-the-bit-size-of-long-on-64-bit-windows

Housebreaking answered 20/8, 2016 at 15:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.