And 3 bytes on a 24-bit system. Yes, I've worked on one. Welcome to the world of embedded devices.
–
dwjDec 29 '08 at 23:13

14

I've worked on 16-bit systems with 20-bit pointers as well. I should go see what sizeof returns in that case...
–
Judge MaygardenDec 29 '08 at 23:16

3

@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.
–
rmeadorDec 29 '08 at 23:22

12

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)
–
Johannes Schaub - litbJan 3 '09 at 16:03

3

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.
–
John5342May 30 '13 at 12:59

@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.
–
EclipseNov 3 '12 at 22:38

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.
–
Kaz DragonMay 31 '13 at 8:01

@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.
–
Kaz DragonNov 4 '13 at 9:16

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.

"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?!
–
Sangeeth SaravanarajApr 17 '12 at 18:27

2

@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 GarvinApr 17 '12 at 20:08

@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.
–
Joseph GarvinApr 17 '12 at 20:10

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.
–
Mihai LimbășanDec 30 '08 at 11:15

Could still return 2, if CHAR_BIT is 16. sizeof() counts in number of chars, not octets.
–
MSaltersApr 6 '09 at 13:56

1

@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"
–
Ben VoigtAug 31 '13 at 2:49

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.

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.
–
Keith ThompsonJul 1 '12 at 1:49

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.

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.

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.

C++ stores each pointer in the one word of computer memory. Word means single slot of memory.
Size of this slot depends on your machine (32 or 64 bit). We can represent 32bit with 4 bytes (1 byte=8bit) and 64bit with 8 bytes. So, if compiler will use one slot for one pointer, that pointer will be 4 or 8 byte respect to your machine type.

For instance:
I used g++ in 64bit machine in order to compile below lines and output is 8byte because of (8byte * 8bit = 64bit).

size_t is tied to the size of the biggest possible single object. char* must be able to address all bytes in all objects. So, size_t can be 2 byte (objects <64KB) even if char* is 4 byte (sufficient for e.g. 65536 objects of 65535 bytes each)
–
MSaltersJan 2 '09 at 15:13

MSalters, you are right: sort of. On closer inspection, the only guarantee is that size_t can address any point in memory. Thus it will always be equal to or greater than sizeof(char *). I will leave my answer up for now so others may learn from it.
–
MaxJan 3 '09 at 9:51