By Joel


2008-12-29 23:03:23 8 Comments

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

17 comments

@Jayhello 2018-06-08 01:10:29

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.

@Hernán 2016-08-20 15:38:13

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://stackoverflow.com/a/384672/48026

@David Thornley 2008-12-29 23:11:15

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.

@dwj 2008-12-29 23:13:34

And 3 bytes on a 24-bit system. Yes, I've worked on one. Welcome to the world of embedded devices.

@Judge Maygarden 2008-12-29 23:16:20

I've worked on 16-bit systems with 20-bit pointers as well. I should go see what sizeof returns in that case...

@rmeador 2008-12-29 23:22:18

@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.

@Jonathan Leffler 2008-12-30 00:10:49

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!

@Jonathan Leffler 2008-12-30 00:14:20

(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.

@Ferruccio 2008-12-30 03:27:55

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!

@ApplePieIsGood 2008-12-30 15:26:17

16 bit systems are easy to find. Any code that runs in THUMB mode on an ARM chip.

@Ben Combee 2008-12-30 16:40:25

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.

@Johannes Schaub - litb 2009-01-03 16:03:26

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)

@Mehrdad Afshari 2009-01-09 13:59:57

Ferruccio: It's not old. My Core 2 Quad processor also supports real mode ;-P

@Eclipse 2009-01-13 22:55:26

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.

@osgx 2010-03-24 00:19:45

itanium sometimes uses 2word (2 pointers) for representing 1 function pointer.

@Jon Hanna 2012-08-10 12:52:51

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.

@Cole Johnson 2012-11-14 06:10:11

@JudgeMaygarden sounds like the 16-bit Real World

@John5342 2013-05-30 12:59:48

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.

@Kobor42 2013-07-16 20:34:15

8 and 16 bit is everywhere. Washing mashines, fridges, micros, remote controllers, car keys.

@gnasher729 2015-08-30 13:34:39

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.

@user1084944 2015-09-23 06:03:20

@gnasher729: I know there are guarantees about casting pointers, but where is there a guarantee about the size and representation?

@Destructor 2016-04-04 15:29:54

@JohannesSchaub-litb: where does the standard says that sizeof(char*) == sizeof(void*) ?

@dud3 2017-04-03 21:00:32

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?

@Sha Vuklia 2018-11-11 01:29:45

@JudgeMaygarden So what did it say?

@supercat 2020-03-23 22:07:06

@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.

@chux - Reinstate Monica 2020-03-23 22:39:39

@supercat 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.

@Rndp13 2015-06-05 03:00:48

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.

@FryGuy 2008-12-29 23:04:24

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

@Kaz Dragon 2013-05-31 08:01:07

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.

@Aaron McDaid 2013-11-02 10:34:03

@KazDragon, sizeof(char*)==1 ? Are you sure? Don't you mean size(char)==1?

@Kaz Dragon 2013-11-04 09:16:36

@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.

@phuclv 2014-03-05 09:20:08

@rsaxvc 2016-04-12 04:26:35

Just curious, @KazDragon can you give an example of a machine where CHAR_BITS=64?

@Kaz Dragon 2016-04-14 07:12:02

@rsaxvc No, but I could build one if I so chose.

@user253751 2019-12-13 16:01:12

@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.

@Ben Voigt 2020-02-14 16:42:48

@user253751: There are of course a number of off-the-shelf DSP chips like that.

@finalsemester.co.in 2014-07-14 19:04:19

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.

@Kobor42 2013-07-16 20:23:54

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.

@Eclipse 2009-01-13 22:53:17

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.

@dalle 2009-02-18 15:21:43

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.

@Gob00st 2012-11-03 18:54:45

gcc 4.72 print all 8 ... Is this undefined in c++ standard ?

@Eclipse 2012-11-03 22:38:47

@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.

@Gob00st 2012-11-03 23:05:25

ok thanks. Then no wonder gcc & VC have different implementation .

@Cole Johnson 2012-11-14 06:10:53

@Eclipse yes there is: char <= short <= int <= long <= long long

@user3207158 2019-11-11 05:25:26

@ColeJohnson where is the relation coming from? Should the first <= be <, namely char < short?

@Cole Johnson 2019-11-12 16:53:43

@user3207158 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.

@Joseph Garvin 2008-12-31 04:19:54

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.

@Sangeeth Saravanaraj 2012-04-17 18:27:40

"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?!

@Joseph Garvin 2012-04-17 20:08:53

@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.

@Joseph Garvin 2012-04-17 20:10:21

@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.

@Sangeeth Saravanaraj 2012-04-17 20:11:15

Thanks for the explanation! :)

@Steve Jessop 2008-12-31 01:39:40

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.

@dmityugov 2008-12-30 10:58:24

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

@Roee Shenberg 2012-05-29 01:45:29

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 flags

@phuclv 2014-03-05 09:20:56

Why are there segments and offsets in x86 while the address space is flat?

@Christopher Creutzig 2014-03-08 09:16:31

@LưuVĩnhPhúc Because it saves space for the very common case of near pointers, which can be encoded shorter.

@phuclv 2014-03-08 10:06:30

@ChristopherCreutzig that means the segments are used for extending address space like PAE?

@Christopher Creutzig 2014-03-09 21:34:42

@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.

@pojo-guy 2017-07-04 18:44:38

@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.

@Darron 2008-12-29 23:50:05

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.

@Keith Thompson 2012-07-01 01:49:32

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.

@Judge Maygarden 2008-12-29 23:17:23

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

@Ed S. 2008-12-29 23:08:39

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.

@Robert Gamble 2008-12-29 23:28:49

On a 32-bit machine with 32-bit bytes, sizeof(char *) could be 1.

@Ed S. 2008-12-30 06:48:00

"...with 32-bit bytes". I didn't know such things existed...fancy that.

@Adriano Varoli Piazza 2008-12-30 11:08:45

On a 32 bit duck, sizeof(char *) returns PI

@Sean Reilly 2008-12-29 23:06:07

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.

@Will Bickford 2008-12-29 23:05:18

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.

@Will Mc 2008-12-29 23:04:52

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.

@Mihai Limbășan 2008-12-30 11:15:29

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.

@Will Mc 2008-12-30 15:52:49

Ah, I see now. Thanks for the info.

@MSalters 2009-04-06 13:56:58

Could still return 2, if CHAR_BIT is 16. sizeof() counts in number of chars, not octets.

@Ben Voigt 2013-08-31 02:49:37

@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"

Related Questions

Sponsored Content

12 Answered Questions

[SOLVED] Why isn&#39;t sizeof for a struct equal to the sum of sizeof of each member?

40 Answered Questions

6 Answered Questions

[SOLVED] What does &quot;dereferencing&quot; a pointer mean?

13 Answered Questions

[SOLVED] How to find the 'sizeof' (a pointer pointing to an array)?

13 Answered Questions

[SOLVED] What is a smart pointer and when should I use one?

21 Answered Questions

[SOLVED] Why should I use a pointer rather than the object itself?

9 Answered Questions

[SOLVED] Why does sizeof(x++) not increment x?

  • 2011-11-22 11:07:16
  • Neigyl R. Noval
  • 29855 View
  • 505 Score
  • 9 Answer
  • Tags:   c sizeof

11 Answered Questions

[SOLVED] How do function pointers in C work?

  • 2009-05-08 15:49:17
  • Yuval Adam
  • 805332 View
  • 1248 Score
  • 11 Answer
  • Tags:   c function-pointers

7 Answered Questions

4 Answered Questions

[SOLVED] Why does sizeof(my_arr)[0] compile and equal sizeof(my_arr[0])?

  • 2017-10-09 19:09:19
  • bgomberg
  • 6579 View
  • 129 Score
  • 4 Answer
  • Tags:   c sizeof

Sponsored Content