size of pointers and architectureIs the sizeof(some pointer) always equal to four?Does the size of pointers vary in C?Where is the x86-64 System V ABI documented?Can pointers be of different sizes?How to detect X32 on Windows?What are the differences between a pointer variable and a reference variable in C++?What is a smart pointer and when should I use one?How do function pointers in C work?Are there any platforms where pointers to different types have different sizes?Improve INSERT-per-second performance of SQLite?Why are elementwise additions much faster in separate loops than in a combined loop?Why does GCC generate 15-20% faster code if I optimize for size instead of speed?Why should I use a pointer rather than the object itself?sizeof Pointer differs for data type on same architectureFor a pointer p, could p < p+1 be false in an extreme case?

My coworkers think I had a long honeymoon. Actually I was diagnosed with cancer. How do I talk about it?

Pronoun introduced before its antecedent

What's the logic behind the the organization of Hamburg's bus transport into "rings"?

Whats the next step after commercial fusion reactors?

Can you please explain this joke: "I'm going bananas is what I tell my bananas before I leave the house"?

Credit card offering 0.5 miles for every cent rounded up. Too good to be true?

You've spoiled/damaged the card

Accidentally renamed tar.gz file to a non tar.gz file, will my file be messed up

PhD student with mental health issues and bad performance

Why don't B747s start takeoffs with full throttle?

What is the right way to float a home lab?

How to supress loops in a digraph?

Does the "6 seconds per round" rule apply to speaking/roleplaying during combat situations?

Identification quotas - TIKZ LaTeX

Funtion to extract float from different price patterns

Opposite of "Squeaky wheel gets the grease"

Is it possible for people to live in the eye of a permanent hypercane?

What's the correct term for a waitress in the Middle Ages?

Traffic law UK, pedestrians

How can drunken, homicidal elves successfully conduct a wild hunt?

Meaning of constructor with multiple pairs of parentheses

Why is Colorado so different politically from nearby states?

Through what methods and mechanisms can a multi-material FDM printer operate?

Is the decompression of compressed and encrypted data without decryption also theoretically impossible?



size of pointers and architecture


Is the sizeof(some pointer) always equal to four?Does the size of pointers vary in C?Where is the x86-64 System V ABI documented?Can pointers be of different sizes?How to detect X32 on Windows?What are the differences between a pointer variable and a reference variable in C++?What is a smart pointer and when should I use one?How do function pointers in C work?Are there any platforms where pointers to different types have different sizes?Improve INSERT-per-second performance of SQLite?Why are elementwise additions much faster in separate loops than in a combined loop?Why does GCC generate 15-20% faster code if I optimize for size instead of speed?Why should I use a pointer rather than the object itself?sizeof Pointer differs for data type on same architectureFor a pointer p, could p < p+1 be false in an extreme case?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








14















By conducting a basic test by running a simple C++ program on a normal desktop PC it seems plausible to suppose that sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits ?



For example: in 32 bits architectures -> 4 bytes and in 64 bits architectures -> 8 bytes.



However I remember reading that, it is not like that in general!



So I was wondering what would be such circumstances?



  • For equality of size of pointers to data types compared with size of pointers
    to other data types

  • For equality of size of pointers to data types compared with size of pointers
    to functions

  • For equality of size of pointers to target architecture









share|improve this question



















  • 5





    On some architectures, not all pointers are the same size. Clearly two different sizes can't both be equal to the same "architecture size". PIC typically has 8 bit data pointer with 14 bit function pointer. 16-bit x86 had 16-bit near and 32-bit far pointers.

    – Ben Voigt
    May 19 at 14:45











  • If your computers architecture used bank switched memory, a pointer may be comprised of two portions: a bank and an address into the bank. If your architecture used segmented memory, a "far" address may be comprised of a segment and offset, and a "near" address may just have an offset. A function pointer may be different from a data pointer in size, and a member pointer may have non-trivial implementation details making it possibly x2 or x3 larger than the architecture..

    – Eljay
    May 19 at 14:46






  • 5





    Is this just asking for a "no, you can't assume that"? Or an open-ended list of every situation where the assumption breaks down? Or what?

    – Useless
    May 19 at 15:19






  • 1





    @Useless Well, the question itself is pretty open, but the answer is very simple. "NEVER assume it if the correctness depends on it."

    – Broman
    May 19 at 15:29






  • 4





    "target architecture bits" how do you define that?

    – Marc Glisse
    May 19 at 15:34

















14















By conducting a basic test by running a simple C++ program on a normal desktop PC it seems plausible to suppose that sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits ?



For example: in 32 bits architectures -> 4 bytes and in 64 bits architectures -> 8 bytes.



However I remember reading that, it is not like that in general!



So I was wondering what would be such circumstances?



  • For equality of size of pointers to data types compared with size of pointers
    to other data types

  • For equality of size of pointers to data types compared with size of pointers
    to functions

  • For equality of size of pointers to target architecture









share|improve this question



















  • 5





    On some architectures, not all pointers are the same size. Clearly two different sizes can't both be equal to the same "architecture size". PIC typically has 8 bit data pointer with 14 bit function pointer. 16-bit x86 had 16-bit near and 32-bit far pointers.

    – Ben Voigt
    May 19 at 14:45











  • If your computers architecture used bank switched memory, a pointer may be comprised of two portions: a bank and an address into the bank. If your architecture used segmented memory, a "far" address may be comprised of a segment and offset, and a "near" address may just have an offset. A function pointer may be different from a data pointer in size, and a member pointer may have non-trivial implementation details making it possibly x2 or x3 larger than the architecture..

    – Eljay
    May 19 at 14:46






  • 5





    Is this just asking for a "no, you can't assume that"? Or an open-ended list of every situation where the assumption breaks down? Or what?

    – Useless
    May 19 at 15:19






  • 1





    @Useless Well, the question itself is pretty open, but the answer is very simple. "NEVER assume it if the correctness depends on it."

    – Broman
    May 19 at 15:29






  • 4





    "target architecture bits" how do you define that?

    – Marc Glisse
    May 19 at 15:34













14












14








14








By conducting a basic test by running a simple C++ program on a normal desktop PC it seems plausible to suppose that sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits ?



For example: in 32 bits architectures -> 4 bytes and in 64 bits architectures -> 8 bytes.



However I remember reading that, it is not like that in general!



So I was wondering what would be such circumstances?



  • For equality of size of pointers to data types compared with size of pointers
    to other data types

  • For equality of size of pointers to data types compared with size of pointers
    to functions

  • For equality of size of pointers to target architecture









share|improve this question
















By conducting a basic test by running a simple C++ program on a normal desktop PC it seems plausible to suppose that sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits ?



For example: in 32 bits architectures -> 4 bytes and in 64 bits architectures -> 8 bytes.



However I remember reading that, it is not like that in general!



So I was wondering what would be such circumstances?



  • For equality of size of pointers to data types compared with size of pointers
    to other data types

  • For equality of size of pointers to data types compared with size of pointers
    to functions

  • For equality of size of pointers to target architecture






c++ c assembly portability






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 21 at 2:25







AKL

















asked May 19 at 14:41









AKLAKL

60811




60811







  • 5





    On some architectures, not all pointers are the same size. Clearly two different sizes can't both be equal to the same "architecture size". PIC typically has 8 bit data pointer with 14 bit function pointer. 16-bit x86 had 16-bit near and 32-bit far pointers.

    – Ben Voigt
    May 19 at 14:45











  • If your computers architecture used bank switched memory, a pointer may be comprised of two portions: a bank and an address into the bank. If your architecture used segmented memory, a "far" address may be comprised of a segment and offset, and a "near" address may just have an offset. A function pointer may be different from a data pointer in size, and a member pointer may have non-trivial implementation details making it possibly x2 or x3 larger than the architecture..

    – Eljay
    May 19 at 14:46






  • 5





    Is this just asking for a "no, you can't assume that"? Or an open-ended list of every situation where the assumption breaks down? Or what?

    – Useless
    May 19 at 15:19






  • 1





    @Useless Well, the question itself is pretty open, but the answer is very simple. "NEVER assume it if the correctness depends on it."

    – Broman
    May 19 at 15:29






  • 4





    "target architecture bits" how do you define that?

    – Marc Glisse
    May 19 at 15:34












  • 5





    On some architectures, not all pointers are the same size. Clearly two different sizes can't both be equal to the same "architecture size". PIC typically has 8 bit data pointer with 14 bit function pointer. 16-bit x86 had 16-bit near and 32-bit far pointers.

    – Ben Voigt
    May 19 at 14:45











  • If your computers architecture used bank switched memory, a pointer may be comprised of two portions: a bank and an address into the bank. If your architecture used segmented memory, a "far" address may be comprised of a segment and offset, and a "near" address may just have an offset. A function pointer may be different from a data pointer in size, and a member pointer may have non-trivial implementation details making it possibly x2 or x3 larger than the architecture..

    – Eljay
    May 19 at 14:46






  • 5





    Is this just asking for a "no, you can't assume that"? Or an open-ended list of every situation where the assumption breaks down? Or what?

    – Useless
    May 19 at 15:19






  • 1





    @Useless Well, the question itself is pretty open, but the answer is very simple. "NEVER assume it if the correctness depends on it."

    – Broman
    May 19 at 15:29






  • 4





    "target architecture bits" how do you define that?

    – Marc Glisse
    May 19 at 15:34







5




5





On some architectures, not all pointers are the same size. Clearly two different sizes can't both be equal to the same "architecture size". PIC typically has 8 bit data pointer with 14 bit function pointer. 16-bit x86 had 16-bit near and 32-bit far pointers.

– Ben Voigt
May 19 at 14:45





On some architectures, not all pointers are the same size. Clearly two different sizes can't both be equal to the same "architecture size". PIC typically has 8 bit data pointer with 14 bit function pointer. 16-bit x86 had 16-bit near and 32-bit far pointers.

– Ben Voigt
May 19 at 14:45













If your computers architecture used bank switched memory, a pointer may be comprised of two portions: a bank and an address into the bank. If your architecture used segmented memory, a "far" address may be comprised of a segment and offset, and a "near" address may just have an offset. A function pointer may be different from a data pointer in size, and a member pointer may have non-trivial implementation details making it possibly x2 or x3 larger than the architecture..

– Eljay
May 19 at 14:46





If your computers architecture used bank switched memory, a pointer may be comprised of two portions: a bank and an address into the bank. If your architecture used segmented memory, a "far" address may be comprised of a segment and offset, and a "near" address may just have an offset. A function pointer may be different from a data pointer in size, and a member pointer may have non-trivial implementation details making it possibly x2 or x3 larger than the architecture..

– Eljay
May 19 at 14:46




5




5





Is this just asking for a "no, you can't assume that"? Or an open-ended list of every situation where the assumption breaks down? Or what?

– Useless
May 19 at 15:19





Is this just asking for a "no, you can't assume that"? Or an open-ended list of every situation where the assumption breaks down? Or what?

– Useless
May 19 at 15:19




1




1





@Useless Well, the question itself is pretty open, but the answer is very simple. "NEVER assume it if the correctness depends on it."

– Broman
May 19 at 15:29





@Useless Well, the question itself is pretty open, but the answer is very simple. "NEVER assume it if the correctness depends on it."

– Broman
May 19 at 15:29




4




4





"target architecture bits" how do you define that?

– Marc Glisse
May 19 at 15:34





"target architecture bits" how do you define that?

– Marc Glisse
May 19 at 15:34












9 Answers
9






active

oldest

votes


















16














No, it is not reasonable to assume. Making this assumption can cause bugs.



The sizes of pointers (and of integer types) in C or C++ are ultimately determined by the C or C++ implementation. Normal C or C++ implementations are heavily influenced by the architectures and the operating systems they target, but they may choose the sizes of their types for reasons other than execution speed, such as goals of supporting smaller memory use, supporting code that was not written to be fully portable to any type sizes, or supporting easier use of big integers.



I have seen a compiler targeted for a 64-bit system but providing 32-bit pointers, for the purpose of building programs with smaller memory use. (It had been observed that the sizes of pointers were a considerable factor in memory consumption, due to the use of many structures with many connections and references using pointers.) Source code written with the assumption that the pointer size equalled the 64-bit register size would break.






share|improve this answer


















  • 3





    The compiler you have seen is most likely GCC with x32 ABI.

    – Ruslan
    May 19 at 17:06







  • 5





    @Ruslan: No, it was not.

    – Eric Postpischil
    May 19 at 18:23






  • 1





    @Ruslan MSVC also has the ability to use 32-bit pointers in 64-bit programs. And on other 64-bit platforms like MIPS, Sparc or PPC it's also common to use 32-bit pointers to save memory, because those architectures don't have a bigger number of registers on the transition to 64-bit like ARM or x86

    – phuclv
    May 20 at 1:38



















11















It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits




Depends. If you're aiming for a quick estimate of memory consumption it can be good enough.




(including pointers to functions)




But here is one important remark. Although most pointers will have the same size, function pointers may differ. It is not guaranteed that a void* will be able to hold a function pointer. At least, this is true for C. I don't know about C++.




So I was wondering what would be such circumstances if any?




It can be tons of reasons why it differs. If your programs correctness depends on this size it is NEVER ok to do such an assumption. Check it up instead. It shouldn't be hard at all.



You can use this macro to check such things at compile time in C:



#include <assert.h>
static_assert(sizeof(void*) == 4, "Pointers are assumed to be exactly 4 bytes");


When compiling, this gives an error message:



$ gcc main.c 
In file included from main.c:1:
main.c:2:1: error: static assertion failed: "Pointers are assumed to be exactly 4 bytes"
static_assert(sizeof(void*) == 4, "Pointers are assumed to be exactly 4 bytes");
^~~~~~~~~~~~~


If you're using C++, you can skip #include <assert.h> because static_assert is a keyword in C++. (And you can use the keyword _Static_assert in C, but it looks ugly, so use the include and the macro instead.)



Since these two lines are so extremely easy to include in your code, there's NO excuse not to do so if your program would not work correctly with the wrong pointer size.






share|improve this answer
































    8















    It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits?




    It might be reasonable, but it isn't reliably correct. So I guess the answer is "no, except when you already know the answer is yes (and aren't worried about portability)".



    Potentially:



    • systems can have different register sizes, and use different underlying widths for data and addressing: it's not apparent what "target architecture bits" even means for such a system, so you have to choose a specific ABI (and once you've done that you know the answer, for that ABI).


    • systems may support different pointer models, such as the old near, far and huge pointers; in that case you need to know what mode your code is being compiled in (and then you know the answer, for that mode)


    • systems may support different pointer sizes, such as the X32 ABI already mentioned, or either of the other popular 64-bit data models described here

    Finally, there's no obvious benefit to this assumption, since you can just use sizeof(T) directly for whatever T you're interested in.



    If you want to convert between integers and pointers, use intptr_t. If you want to store integers and pointers in the same space, just use a union.






    share|improve this answer






























      6














      Target architecture "bits" says about registers size. Ex. Intel 8051 is 8-bit and operates on 8-bit registers, but (external)RAM and (external)ROM is accessed with 16-bit values.






      share|improve this answer























      • This should really be a comment.

        – fuz
        May 19 at 17:16











      • @MamCieNaHita you are right and I just now remembered that the same goes for AVR-8. But from other comments it appears that it is even more complex than that! Thank you for reminding me.

        – AKL
        May 19 at 18:53












      • @fuz The question was asking "what would be circumstances in which the target architecture bit-ness is different from the pointer size". The answer is fine, it's the question that's too open ended IMHO.

        – Cubic
        May 20 at 9:26


















      4















      It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits?




      If you look at all types of CPUs (including microcontrollers) currently being produced, I would say no.



      Extreme counterexamples would be architectures where two different pointer sizes are used in the same program:



      x86, 16-bit



      In MS-DOS and 16-bit Windows, a "normal" program used both 16- and 32-bit pointers.



      x86, 32-bit segmented



      There were only a few, less known operating systems using this memory model.



      Programs typically used both 32- and 48-bit pointers.



      STM8A



      This modern automotive 8-bit CPU uses 16- and 24-bit pointers. Both in the same program, of course.



      AVR tiny series



      RAM is addressed using 8-bit pointers, Flash is addressed using 16-bit pointers.



      (However, AVR tiny cannot be programmed with C++, as far as I know.)






      share|improve this answer

























      • GCC has an AVR back-end; I assume you can at least compile a function using std:: algorithms, if not containers that do dynamic allocation.

        – Peter Cordes
        May 19 at 21:20











      • If I'm remembering correctly, the 8086 didn't really have 32-bit pointers, which would have allowed a 4 Gbyte address space. It had 24-bit FAR pointers in a segmented address space, where each offset addressed 64K bytes (the same as a NEAR pointer), and the segment register allowed a segment to start on any 256 byte boundary in memory, giving the 1 MByte of address space.

        – jamesqf
        May 20 at 4:42












      • @jamesqf The segment registers on x86 are 16 bits wide, not 8 bits. So a 16-bit far pointer is 32 bits in size. In "real mode" (8086) segments can be aligned on any 16-byte boundary. And the segmented addresses 0x7C0:0 and 0x0:7C00 point to the same byte in RAM but they have a different meaning when being used as code pointers.

        – Martin Rosenau
        May 20 at 19:41












      • @Martin Rosenau: Yes. Maybe my comment wasn't clear: the segment:offset register pair occupies 32 bits, but because of the way they're implemented, they only allow for a 24-bit address space. (And if memory serves, you had to manipulate segment & offset registers separately at the assembly level.)

        – jamesqf
        May 21 at 20:21











      • @jamesqf It depends. In "real mode" (8086 mode) (2^20)+(2^16)-16 data bytes can be accessed in memory. This means that there are effectively less than 21 address bits. Hypothetically, an 8086 has 2^32 addresses for code that cannot be substituted. This means that every of these 2^32 addresses has a different meaning and cannot be replaced by another address! This means that code pointers are really effectively 32-bits wide on a 8086. 16-bit code running on a 80386 can address more than 2^29 data bytes, so the effective address width is 30 bits using 16:16 segmented addressing.

        – Martin Rosenau
        May 21 at 21:15



















      3














      It's not correct, for example DOS pointers (16 bit) can be far (seg+ofs).



      However, for the usual targets (Windows, OSX, Linux, Android, iOS) then it's correct. Because they all use the flat programming model which relies on paging.



      In theory, you can also have systems which uses only the lower 32 bits when in x64. An example is a Windows executable linked without LARGEADDRESSAWARE. However this is to help the programmer avoid bugs when switching to x64. The pointers are truncated to 32 bits, but they are still 64 bit.



      In x64 operating systems then this assumption is always true, because the flat mode is the only valid one. Long mode in CPU forces GDT entries to be 64 bit flat.



      One also mentions a x32 ABI, I believe it is based on the same paging technology, forcing all pointers to be mapped to the lower 4gb. However this must be based to the same theory as in Windows. In x64 you can only have flat mode.



      In 32 bit protected mode you could have pointers up to 48 bits. (Segmented mode). You can also have callgates. But, no operating system uses that mode.






      share|improve this answer




















      • 2





        x86 32-bit protected mode is used by every 32-bit x86 OS. But (almost?) all of them use a flat memory model, which I think is the point you're making. Anyway yes, a seg:off "far" pointer would take 6 bytes in protected mode, but you still only have 4GB of actual addressable memory. Segment base + offset produces a 32-bit linear address. With paging disabled it's a 32-bit physical address. With paging enabled, it's a 32-bit virtual address. PAE can let separate processes each use a separate 4GB of physical memory at the same time by translating 32-bit virtual to 36-bit physical addresses.

        – Peter Cordes
        May 19 at 16:03






      • 1





        The Linux x32 ABI and other ILP32 ABIs in general don't necessarily require paging. You could in theory have an OS that loads position-independent code at different physical addresses within the low 32 bits of physical address space.

        – Peter Cordes
        May 19 at 16:05











      • Nitpick: long mode ignores the base/limit in GDT entries selected by segments other than FS/GS, rather than requiring them to be 0 / -1. And "mapped" is the wrong word for ensuring all pointers are in the low 4GB, that phrasing seems to imply arbitrary virtual addresses mapped to the low 4GB of physical memory. (And BTW, it's actually the low 2GB of virtual address space, so zero- and sign- extension of 32-bit absolute pointers are both valid. e.g. mov edi, array (zero-extended immediate) or add rax, [array + rcx] (sign extended disp32) can both be used for static addresses.

        – Peter Cordes
        May 19 at 16:25


















      3














      For correctness, you cannot assume anything. You have to check and be prepared to deal with weird situations.



      As a general rule of thumb, it is a reasonable default assumption.



      It's not universally true though. See the X32 ABI, for example, which uses 32bit pointers on 64bit architectures to save a bit of memory and cache footprint. Same for the ILP32 ABI on AArch64.



      So, for guesstimating memory use, you can use your assumption and it will often be right.






      share|improve this answer




















      • 2





        PAE isn't relevant to C++ programming on any existing C++ implementation. It doesn't increase the size of virtual address space, only physical. And it only works when paging is enabled, so in a hypothetical freestanding C++ program that runs with paging disabled it's no help in addressing more than 4GB of physical memory.

        – Peter Cordes
        May 19 at 15:52












      • @PeterCordes - Good point. Removed

        – Jesper Juhl
        May 19 at 15:55











      • @JesperJuhl There are way too many architectures (e.g., base & displacement pointers) and language systems (e.g. LISP) where pointers to different types are of different lengths. If you include pointers-to-functions, as OP explicitly did, There are several cases where the size of the pointer depends on the number of paramaters passed and the return value of the function. This is a bad assumption for any portability intention, and can get you in deep before you realize the problems. Your answer's last two sentences should be the first two.

        – mpez0
        May 19 at 16:08







      • 1





        @mpez0 I know. And yes, of course it's a bad assumption for portability, which is why I explicitly said that it was an ok assumption for guesstimating memory use, but useless for correctness.

        – Jesper Juhl
        May 19 at 16:10











      • @mpez0 - "Your answer's last two sentences should be the first two" - better now?

        – Jesper Juhl
        May 21 at 17:40


















      1














      Historically, on microcomputers and microcontrollers, pointers were often wider than general-purpose registers so that the CPU could address enough memory and still fit within the transistor budget. Most 8-bit CPUs (such as the 8080, Z80 or 6502) had 16-bit addresses.



      Today, a mismatch is more likely to be because an app doesn’t need multiple gigabytes of data, so saving four bytes of memory on every pointer is a win.



      Both C and C++ provide separate size_t, uintptr_t and off_t types, representing the largest possible object size (which might be smaller than the size of a pointer if the memory model is not flat), an integral type wide enough to hold a pointer, and a file offset (often wider than the largest object allowed in memory), respectively. A size_t (unsigned) or ptrdiff_t (signed) is the most portable way to get the native word size. Additionally, POSIX guarantees that the system compiler has some flag that means a long can hold any of these, but you cannot always assume so.






      share|improve this answer




















      • 1





        Any reason you left out signed intptr_t? Anyway, worth pointing out that [u]intptr_t can hold any pointer, while size_t only has to hold the max object size. On a machine without a flat memory model, these can easily be different widths. e.g. on x86-16 with far pointers being possible, uintptr_t has to be 32-bit, but size_t can be 16-bit.

        – Peter Cordes
        May 20 at 0:19






      • 1





        (Note that most implementations restrict object size to SIZE_MAX/2 or less, so ptrdiff_t can't overflow with char arrays.) Why is the maximum size of an array "too large"?

        – Peter Cordes
        May 20 at 0:27











      • off_t is for file sizes / positions. It can be and often is 64-bit on a purely 32-bit system, and mentioning it here makes zero sense. Also, none of the types you mentioned are guaranteed to find the max register width, though: a modern ILP32 ABI on a 64-bit architecture will typically have 32-bit size_t, uintptr_t, and ptrdiff_t. So if you use that to decide if the machine has efficient long long / uint64_t, you'll incorrectly rule out x32 on x86-64 and ILP32 on AArch64, for example. You could additionally check #ifdef __SIZEOF_INT128__ because GCC defines that on 64-bit.

        – Peter Cordes
        May 20 at 0:27












      • @PeterCordes I don’t think we disagree. I mentioned only uintptr_t because it’s exactly the same width as the signed counterpart, and the other two types are unsigned.

        – Davislor
        May 20 at 0:57











      • @PeterCordes uintptr_t doesn't have to be anything, it is an optional type

        – M.M
        May 20 at 1:50


















      0














      Generally pointers will be size 2 on a 16-bit system, 3 on a 24-bit system, 4 on a 32-bit system, and 8 on a 64-bit system. It depends on the ABI and C implementation. AMD has long and legacy modes, and there are differences between AMD64 and Intel64 for Assembly language programmers but these are hidden for higher level languages.



      Any problems with C/C++ code is likely to be due to poor programming practices and ignoring compiler warnings. See: "20 issues of porting C++ code to the 64-bit platform".



      See also: "Can pointers be of different sizes?" and LRiO's answer:




      ... you are asking about C++ and its compliant implementations, not some specific physical machine. I'd have to quote the entire standard in order to prove it, but the simple fact is that it makes no guarantees on the result of sizeof(T*) for any T, and (as a corollary) no guarantees that sizeof(T1*) == sizeof(T2*) for any T1 and T2).




      Note: Where is answered by JeremyP, C99 section 6.3.2.3, subsection 8:




      A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.




      In GCC you can avoid incorrect assumptions by using built-in functions: "Object Size Checking Built-in Functions":




      Built-in Function: size_t __builtin_object_size (const void * ptr, int type)



      is a built-in construct that returns a constant number of bytes from ptr to the end of the object ptr pointer points to (if known at compile time). To determine the sizes of dynamically allocated objects the function relies on the allocation functions called to obtain the storage to be declared with the alloc_size attribute (see Common Function Attributes). __builtin_object_size never evaluates its arguments for side effects. If there are any side effects in them, it returns (size_t) -1 for type 0 or 1 and (size_t) 0 for type 2 or 3. If there are multiple objects ptr can point to and all of them are known at compile time, the returned number is the maximum of remaining byte counts in those objects if type & 2 is 0 and minimum if nonzero. If it is not possible to determine which objects ptr points to at compile time, __builtin_object_size should return (size_t) -1 for type 0 or 1 and (size_t) 0 for type 2 or 3.







      share|improve this answer























      • The differences between Intel64 and AMD64 are very minor and totally irrelevant to discussion of pointer widths. They're pretty much limited to a few kernel system-management differences; normal computation is identical across all x86-64; that's why we don't need separate binaries for Intel vs. AMD CPUs.

        – Peter Cordes
        May 20 at 1:33






      • 1





        You're assuming that CHAR_BIT is defined as 8. A 24-bit system is probably a DSP with 24-bit word-addressable memory, so a char is probably also 24-bit. Thus sizeof() everything = 1.

        – Peter Cordes
        May 20 at 1:35











      • What did you say here or in the Q&As I linked to?

        – Rob
        May 20 at 1:44











      • What did I say? I haven't commented on or answered that linked question, no idea what point you're making. Maybe you mean that a 24-bit system might not have 24-bit pointers; that's certainly possible, a C++ implementation is allowed to exist where some or all kinds of pointers are wider than its 24-bit char/int. But I meant for a "normal" 24-bit DSP, it probably wouldn't have byte-addressable memory with 3-byte "words", so a normal C++ implementation on it would probably have sizeof(void*) = sizeof(int*) = sizeof(char) = sizeof(int) = 1.

        – Peter Cordes
        May 20 at 2:06











      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56208872%2fsize-of-pointers-and-architecture%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      9 Answers
      9






      active

      oldest

      votes








      9 Answers
      9






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      16














      No, it is not reasonable to assume. Making this assumption can cause bugs.



      The sizes of pointers (and of integer types) in C or C++ are ultimately determined by the C or C++ implementation. Normal C or C++ implementations are heavily influenced by the architectures and the operating systems they target, but they may choose the sizes of their types for reasons other than execution speed, such as goals of supporting smaller memory use, supporting code that was not written to be fully portable to any type sizes, or supporting easier use of big integers.



      I have seen a compiler targeted for a 64-bit system but providing 32-bit pointers, for the purpose of building programs with smaller memory use. (It had been observed that the sizes of pointers were a considerable factor in memory consumption, due to the use of many structures with many connections and references using pointers.) Source code written with the assumption that the pointer size equalled the 64-bit register size would break.






      share|improve this answer


















      • 3





        The compiler you have seen is most likely GCC with x32 ABI.

        – Ruslan
        May 19 at 17:06







      • 5





        @Ruslan: No, it was not.

        – Eric Postpischil
        May 19 at 18:23






      • 1





        @Ruslan MSVC also has the ability to use 32-bit pointers in 64-bit programs. And on other 64-bit platforms like MIPS, Sparc or PPC it's also common to use 32-bit pointers to save memory, because those architectures don't have a bigger number of registers on the transition to 64-bit like ARM or x86

        – phuclv
        May 20 at 1:38
















      16














      No, it is not reasonable to assume. Making this assumption can cause bugs.



      The sizes of pointers (and of integer types) in C or C++ are ultimately determined by the C or C++ implementation. Normal C or C++ implementations are heavily influenced by the architectures and the operating systems they target, but they may choose the sizes of their types for reasons other than execution speed, such as goals of supporting smaller memory use, supporting code that was not written to be fully portable to any type sizes, or supporting easier use of big integers.



      I have seen a compiler targeted for a 64-bit system but providing 32-bit pointers, for the purpose of building programs with smaller memory use. (It had been observed that the sizes of pointers were a considerable factor in memory consumption, due to the use of many structures with many connections and references using pointers.) Source code written with the assumption that the pointer size equalled the 64-bit register size would break.






      share|improve this answer


















      • 3





        The compiler you have seen is most likely GCC with x32 ABI.

        – Ruslan
        May 19 at 17:06







      • 5





        @Ruslan: No, it was not.

        – Eric Postpischil
        May 19 at 18:23






      • 1





        @Ruslan MSVC also has the ability to use 32-bit pointers in 64-bit programs. And on other 64-bit platforms like MIPS, Sparc or PPC it's also common to use 32-bit pointers to save memory, because those architectures don't have a bigger number of registers on the transition to 64-bit like ARM or x86

        – phuclv
        May 20 at 1:38














      16












      16








      16







      No, it is not reasonable to assume. Making this assumption can cause bugs.



      The sizes of pointers (and of integer types) in C or C++ are ultimately determined by the C or C++ implementation. Normal C or C++ implementations are heavily influenced by the architectures and the operating systems they target, but they may choose the sizes of their types for reasons other than execution speed, such as goals of supporting smaller memory use, supporting code that was not written to be fully portable to any type sizes, or supporting easier use of big integers.



      I have seen a compiler targeted for a 64-bit system but providing 32-bit pointers, for the purpose of building programs with smaller memory use. (It had been observed that the sizes of pointers were a considerable factor in memory consumption, due to the use of many structures with many connections and references using pointers.) Source code written with the assumption that the pointer size equalled the 64-bit register size would break.






      share|improve this answer













      No, it is not reasonable to assume. Making this assumption can cause bugs.



      The sizes of pointers (and of integer types) in C or C++ are ultimately determined by the C or C++ implementation. Normal C or C++ implementations are heavily influenced by the architectures and the operating systems they target, but they may choose the sizes of their types for reasons other than execution speed, such as goals of supporting smaller memory use, supporting code that was not written to be fully portable to any type sizes, or supporting easier use of big integers.



      I have seen a compiler targeted for a 64-bit system but providing 32-bit pointers, for the purpose of building programs with smaller memory use. (It had been observed that the sizes of pointers were a considerable factor in memory consumption, due to the use of many structures with many connections and references using pointers.) Source code written with the assumption that the pointer size equalled the 64-bit register size would break.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered May 19 at 15:04









      Eric PostpischilEric Postpischil

      84.5k892171




      84.5k892171







      • 3





        The compiler you have seen is most likely GCC with x32 ABI.

        – Ruslan
        May 19 at 17:06







      • 5





        @Ruslan: No, it was not.

        – Eric Postpischil
        May 19 at 18:23






      • 1





        @Ruslan MSVC also has the ability to use 32-bit pointers in 64-bit programs. And on other 64-bit platforms like MIPS, Sparc or PPC it's also common to use 32-bit pointers to save memory, because those architectures don't have a bigger number of registers on the transition to 64-bit like ARM or x86

        – phuclv
        May 20 at 1:38













      • 3





        The compiler you have seen is most likely GCC with x32 ABI.

        – Ruslan
        May 19 at 17:06







      • 5





        @Ruslan: No, it was not.

        – Eric Postpischil
        May 19 at 18:23






      • 1





        @Ruslan MSVC also has the ability to use 32-bit pointers in 64-bit programs. And on other 64-bit platforms like MIPS, Sparc or PPC it's also common to use 32-bit pointers to save memory, because those architectures don't have a bigger number of registers on the transition to 64-bit like ARM or x86

        – phuclv
        May 20 at 1:38








      3




      3





      The compiler you have seen is most likely GCC with x32 ABI.

      – Ruslan
      May 19 at 17:06






      The compiler you have seen is most likely GCC with x32 ABI.

      – Ruslan
      May 19 at 17:06





      5




      5





      @Ruslan: No, it was not.

      – Eric Postpischil
      May 19 at 18:23





      @Ruslan: No, it was not.

      – Eric Postpischil
      May 19 at 18:23




      1




      1





      @Ruslan MSVC also has the ability to use 32-bit pointers in 64-bit programs. And on other 64-bit platforms like MIPS, Sparc or PPC it's also common to use 32-bit pointers to save memory, because those architectures don't have a bigger number of registers on the transition to 64-bit like ARM or x86

      – phuclv
      May 20 at 1:38






      @Ruslan MSVC also has the ability to use 32-bit pointers in 64-bit programs. And on other 64-bit platforms like MIPS, Sparc or PPC it's also common to use 32-bit pointers to save memory, because those architectures don't have a bigger number of registers on the transition to 64-bit like ARM or x86

      – phuclv
      May 20 at 1:38














      11















      It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits




      Depends. If you're aiming for a quick estimate of memory consumption it can be good enough.




      (including pointers to functions)




      But here is one important remark. Although most pointers will have the same size, function pointers may differ. It is not guaranteed that a void* will be able to hold a function pointer. At least, this is true for C. I don't know about C++.




      So I was wondering what would be such circumstances if any?




      It can be tons of reasons why it differs. If your programs correctness depends on this size it is NEVER ok to do such an assumption. Check it up instead. It shouldn't be hard at all.



      You can use this macro to check such things at compile time in C:



      #include <assert.h>
      static_assert(sizeof(void*) == 4, "Pointers are assumed to be exactly 4 bytes");


      When compiling, this gives an error message:



      $ gcc main.c 
      In file included from main.c:1:
      main.c:2:1: error: static assertion failed: "Pointers are assumed to be exactly 4 bytes"
      static_assert(sizeof(void*) == 4, "Pointers are assumed to be exactly 4 bytes");
      ^~~~~~~~~~~~~


      If you're using C++, you can skip #include <assert.h> because static_assert is a keyword in C++. (And you can use the keyword _Static_assert in C, but it looks ugly, so use the include and the macro instead.)



      Since these two lines are so extremely easy to include in your code, there's NO excuse not to do so if your program would not work correctly with the wrong pointer size.






      share|improve this answer





























        11















        It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits




        Depends. If you're aiming for a quick estimate of memory consumption it can be good enough.




        (including pointers to functions)




        But here is one important remark. Although most pointers will have the same size, function pointers may differ. It is not guaranteed that a void* will be able to hold a function pointer. At least, this is true for C. I don't know about C++.




        So I was wondering what would be such circumstances if any?




        It can be tons of reasons why it differs. If your programs correctness depends on this size it is NEVER ok to do such an assumption. Check it up instead. It shouldn't be hard at all.



        You can use this macro to check such things at compile time in C:



        #include <assert.h>
        static_assert(sizeof(void*) == 4, "Pointers are assumed to be exactly 4 bytes");


        When compiling, this gives an error message:



        $ gcc main.c 
        In file included from main.c:1:
        main.c:2:1: error: static assertion failed: "Pointers are assumed to be exactly 4 bytes"
        static_assert(sizeof(void*) == 4, "Pointers are assumed to be exactly 4 bytes");
        ^~~~~~~~~~~~~


        If you're using C++, you can skip #include <assert.h> because static_assert is a keyword in C++. (And you can use the keyword _Static_assert in C, but it looks ugly, so use the include and the macro instead.)



        Since these two lines are so extremely easy to include in your code, there's NO excuse not to do so if your program would not work correctly with the wrong pointer size.






        share|improve this answer



























          11












          11








          11








          It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits




          Depends. If you're aiming for a quick estimate of memory consumption it can be good enough.




          (including pointers to functions)




          But here is one important remark. Although most pointers will have the same size, function pointers may differ. It is not guaranteed that a void* will be able to hold a function pointer. At least, this is true for C. I don't know about C++.




          So I was wondering what would be such circumstances if any?




          It can be tons of reasons why it differs. If your programs correctness depends on this size it is NEVER ok to do such an assumption. Check it up instead. It shouldn't be hard at all.



          You can use this macro to check such things at compile time in C:



          #include <assert.h>
          static_assert(sizeof(void*) == 4, "Pointers are assumed to be exactly 4 bytes");


          When compiling, this gives an error message:



          $ gcc main.c 
          In file included from main.c:1:
          main.c:2:1: error: static assertion failed: "Pointers are assumed to be exactly 4 bytes"
          static_assert(sizeof(void*) == 4, "Pointers are assumed to be exactly 4 bytes");
          ^~~~~~~~~~~~~


          If you're using C++, you can skip #include <assert.h> because static_assert is a keyword in C++. (And you can use the keyword _Static_assert in C, but it looks ugly, so use the include and the macro instead.)



          Since these two lines are so extremely easy to include in your code, there's NO excuse not to do so if your program would not work correctly with the wrong pointer size.






          share|improve this answer
















          It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits




          Depends. If you're aiming for a quick estimate of memory consumption it can be good enough.




          (including pointers to functions)




          But here is one important remark. Although most pointers will have the same size, function pointers may differ. It is not guaranteed that a void* will be able to hold a function pointer. At least, this is true for C. I don't know about C++.




          So I was wondering what would be such circumstances if any?




          It can be tons of reasons why it differs. If your programs correctness depends on this size it is NEVER ok to do such an assumption. Check it up instead. It shouldn't be hard at all.



          You can use this macro to check such things at compile time in C:



          #include <assert.h>
          static_assert(sizeof(void*) == 4, "Pointers are assumed to be exactly 4 bytes");


          When compiling, this gives an error message:



          $ gcc main.c 
          In file included from main.c:1:
          main.c:2:1: error: static assertion failed: "Pointers are assumed to be exactly 4 bytes"
          static_assert(sizeof(void*) == 4, "Pointers are assumed to be exactly 4 bytes");
          ^~~~~~~~~~~~~


          If you're using C++, you can skip #include <assert.h> because static_assert is a keyword in C++. (And you can use the keyword _Static_assert in C, but it looks ugly, so use the include and the macro instead.)



          Since these two lines are so extremely easy to include in your code, there's NO excuse not to do so if your program would not work correctly with the wrong pointer size.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited May 20 at 7:33

























          answered May 19 at 14:59









          BromanBroman

          9,078112645




          9,078112645





















              8















              It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits?




              It might be reasonable, but it isn't reliably correct. So I guess the answer is "no, except when you already know the answer is yes (and aren't worried about portability)".



              Potentially:



              • systems can have different register sizes, and use different underlying widths for data and addressing: it's not apparent what "target architecture bits" even means for such a system, so you have to choose a specific ABI (and once you've done that you know the answer, for that ABI).


              • systems may support different pointer models, such as the old near, far and huge pointers; in that case you need to know what mode your code is being compiled in (and then you know the answer, for that mode)


              • systems may support different pointer sizes, such as the X32 ABI already mentioned, or either of the other popular 64-bit data models described here

              Finally, there's no obvious benefit to this assumption, since you can just use sizeof(T) directly for whatever T you're interested in.



              If you want to convert between integers and pointers, use intptr_t. If you want to store integers and pointers in the same space, just use a union.






              share|improve this answer



























                8















                It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits?




                It might be reasonable, but it isn't reliably correct. So I guess the answer is "no, except when you already know the answer is yes (and aren't worried about portability)".



                Potentially:



                • systems can have different register sizes, and use different underlying widths for data and addressing: it's not apparent what "target architecture bits" even means for such a system, so you have to choose a specific ABI (and once you've done that you know the answer, for that ABI).


                • systems may support different pointer models, such as the old near, far and huge pointers; in that case you need to know what mode your code is being compiled in (and then you know the answer, for that mode)


                • systems may support different pointer sizes, such as the X32 ABI already mentioned, or either of the other popular 64-bit data models described here

                Finally, there's no obvious benefit to this assumption, since you can just use sizeof(T) directly for whatever T you're interested in.



                If you want to convert between integers and pointers, use intptr_t. If you want to store integers and pointers in the same space, just use a union.






                share|improve this answer

























                  8












                  8








                  8








                  It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits?




                  It might be reasonable, but it isn't reliably correct. So I guess the answer is "no, except when you already know the answer is yes (and aren't worried about portability)".



                  Potentially:



                  • systems can have different register sizes, and use different underlying widths for data and addressing: it's not apparent what "target architecture bits" even means for such a system, so you have to choose a specific ABI (and once you've done that you know the answer, for that ABI).


                  • systems may support different pointer models, such as the old near, far and huge pointers; in that case you need to know what mode your code is being compiled in (and then you know the answer, for that mode)


                  • systems may support different pointer sizes, such as the X32 ABI already mentioned, or either of the other popular 64-bit data models described here

                  Finally, there's no obvious benefit to this assumption, since you can just use sizeof(T) directly for whatever T you're interested in.



                  If you want to convert between integers and pointers, use intptr_t. If you want to store integers and pointers in the same space, just use a union.






                  share|improve this answer














                  It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits?




                  It might be reasonable, but it isn't reliably correct. So I guess the answer is "no, except when you already know the answer is yes (and aren't worried about portability)".



                  Potentially:



                  • systems can have different register sizes, and use different underlying widths for data and addressing: it's not apparent what "target architecture bits" even means for such a system, so you have to choose a specific ABI (and once you've done that you know the answer, for that ABI).


                  • systems may support different pointer models, such as the old near, far and huge pointers; in that case you need to know what mode your code is being compiled in (and then you know the answer, for that mode)


                  • systems may support different pointer sizes, such as the X32 ABI already mentioned, or either of the other popular 64-bit data models described here

                  Finally, there's no obvious benefit to this assumption, since you can just use sizeof(T) directly for whatever T you're interested in.



                  If you want to convert between integers and pointers, use intptr_t. If you want to store integers and pointers in the same space, just use a union.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered May 19 at 15:52









                  UselessUseless

                  45.2k55697




                  45.2k55697





















                      6














                      Target architecture "bits" says about registers size. Ex. Intel 8051 is 8-bit and operates on 8-bit registers, but (external)RAM and (external)ROM is accessed with 16-bit values.






                      share|improve this answer























                      • This should really be a comment.

                        – fuz
                        May 19 at 17:16











                      • @MamCieNaHita you are right and I just now remembered that the same goes for AVR-8. But from other comments it appears that it is even more complex than that! Thank you for reminding me.

                        – AKL
                        May 19 at 18:53












                      • @fuz The question was asking "what would be circumstances in which the target architecture bit-ness is different from the pointer size". The answer is fine, it's the question that's too open ended IMHO.

                        – Cubic
                        May 20 at 9:26















                      6














                      Target architecture "bits" says about registers size. Ex. Intel 8051 is 8-bit and operates on 8-bit registers, but (external)RAM and (external)ROM is accessed with 16-bit values.






                      share|improve this answer























                      • This should really be a comment.

                        – fuz
                        May 19 at 17:16











                      • @MamCieNaHita you are right and I just now remembered that the same goes for AVR-8. But from other comments it appears that it is even more complex than that! Thank you for reminding me.

                        – AKL
                        May 19 at 18:53












                      • @fuz The question was asking "what would be circumstances in which the target architecture bit-ness is different from the pointer size". The answer is fine, it's the question that's too open ended IMHO.

                        – Cubic
                        May 20 at 9:26













                      6












                      6








                      6







                      Target architecture "bits" says about registers size. Ex. Intel 8051 is 8-bit and operates on 8-bit registers, but (external)RAM and (external)ROM is accessed with 16-bit values.






                      share|improve this answer













                      Target architecture "bits" says about registers size. Ex. Intel 8051 is 8-bit and operates on 8-bit registers, but (external)RAM and (external)ROM is accessed with 16-bit values.







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered May 19 at 14:45









                      MamCieNaHitaMamCieNaHita

                      886




                      886












                      • This should really be a comment.

                        – fuz
                        May 19 at 17:16











                      • @MamCieNaHita you are right and I just now remembered that the same goes for AVR-8. But from other comments it appears that it is even more complex than that! Thank you for reminding me.

                        – AKL
                        May 19 at 18:53












                      • @fuz The question was asking "what would be circumstances in which the target architecture bit-ness is different from the pointer size". The answer is fine, it's the question that's too open ended IMHO.

                        – Cubic
                        May 20 at 9:26

















                      • This should really be a comment.

                        – fuz
                        May 19 at 17:16











                      • @MamCieNaHita you are right and I just now remembered that the same goes for AVR-8. But from other comments it appears that it is even more complex than that! Thank you for reminding me.

                        – AKL
                        May 19 at 18:53












                      • @fuz The question was asking "what would be circumstances in which the target architecture bit-ness is different from the pointer size". The answer is fine, it's the question that's too open ended IMHO.

                        – Cubic
                        May 20 at 9:26
















                      This should really be a comment.

                      – fuz
                      May 19 at 17:16





                      This should really be a comment.

                      – fuz
                      May 19 at 17:16













                      @MamCieNaHita you are right and I just now remembered that the same goes for AVR-8. But from other comments it appears that it is even more complex than that! Thank you for reminding me.

                      – AKL
                      May 19 at 18:53






                      @MamCieNaHita you are right and I just now remembered that the same goes for AVR-8. But from other comments it appears that it is even more complex than that! Thank you for reminding me.

                      – AKL
                      May 19 at 18:53














                      @fuz The question was asking "what would be circumstances in which the target architecture bit-ness is different from the pointer size". The answer is fine, it's the question that's too open ended IMHO.

                      – Cubic
                      May 20 at 9:26





                      @fuz The question was asking "what would be circumstances in which the target architecture bit-ness is different from the pointer size". The answer is fine, it's the question that's too open ended IMHO.

                      – Cubic
                      May 20 at 9:26











                      4















                      It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits?




                      If you look at all types of CPUs (including microcontrollers) currently being produced, I would say no.



                      Extreme counterexamples would be architectures where two different pointer sizes are used in the same program:



                      x86, 16-bit



                      In MS-DOS and 16-bit Windows, a "normal" program used both 16- and 32-bit pointers.



                      x86, 32-bit segmented



                      There were only a few, less known operating systems using this memory model.



                      Programs typically used both 32- and 48-bit pointers.



                      STM8A



                      This modern automotive 8-bit CPU uses 16- and 24-bit pointers. Both in the same program, of course.



                      AVR tiny series



                      RAM is addressed using 8-bit pointers, Flash is addressed using 16-bit pointers.



                      (However, AVR tiny cannot be programmed with C++, as far as I know.)






                      share|improve this answer

























                      • GCC has an AVR back-end; I assume you can at least compile a function using std:: algorithms, if not containers that do dynamic allocation.

                        – Peter Cordes
                        May 19 at 21:20











                      • If I'm remembering correctly, the 8086 didn't really have 32-bit pointers, which would have allowed a 4 Gbyte address space. It had 24-bit FAR pointers in a segmented address space, where each offset addressed 64K bytes (the same as a NEAR pointer), and the segment register allowed a segment to start on any 256 byte boundary in memory, giving the 1 MByte of address space.

                        – jamesqf
                        May 20 at 4:42












                      • @jamesqf The segment registers on x86 are 16 bits wide, not 8 bits. So a 16-bit far pointer is 32 bits in size. In "real mode" (8086) segments can be aligned on any 16-byte boundary. And the segmented addresses 0x7C0:0 and 0x0:7C00 point to the same byte in RAM but they have a different meaning when being used as code pointers.

                        – Martin Rosenau
                        May 20 at 19:41












                      • @Martin Rosenau: Yes. Maybe my comment wasn't clear: the segment:offset register pair occupies 32 bits, but because of the way they're implemented, they only allow for a 24-bit address space. (And if memory serves, you had to manipulate segment & offset registers separately at the assembly level.)

                        – jamesqf
                        May 21 at 20:21











                      • @jamesqf It depends. In "real mode" (8086 mode) (2^20)+(2^16)-16 data bytes can be accessed in memory. This means that there are effectively less than 21 address bits. Hypothetically, an 8086 has 2^32 addresses for code that cannot be substituted. This means that every of these 2^32 addresses has a different meaning and cannot be replaced by another address! This means that code pointers are really effectively 32-bits wide on a 8086. 16-bit code running on a 80386 can address more than 2^29 data bytes, so the effective address width is 30 bits using 16:16 segmented addressing.

                        – Martin Rosenau
                        May 21 at 21:15
















                      4















                      It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits?




                      If you look at all types of CPUs (including microcontrollers) currently being produced, I would say no.



                      Extreme counterexamples would be architectures where two different pointer sizes are used in the same program:



                      x86, 16-bit



                      In MS-DOS and 16-bit Windows, a "normal" program used both 16- and 32-bit pointers.



                      x86, 32-bit segmented



                      There were only a few, less known operating systems using this memory model.



                      Programs typically used both 32- and 48-bit pointers.



                      STM8A



                      This modern automotive 8-bit CPU uses 16- and 24-bit pointers. Both in the same program, of course.



                      AVR tiny series



                      RAM is addressed using 8-bit pointers, Flash is addressed using 16-bit pointers.



                      (However, AVR tiny cannot be programmed with C++, as far as I know.)






                      share|improve this answer

























                      • GCC has an AVR back-end; I assume you can at least compile a function using std:: algorithms, if not containers that do dynamic allocation.

                        – Peter Cordes
                        May 19 at 21:20











                      • If I'm remembering correctly, the 8086 didn't really have 32-bit pointers, which would have allowed a 4 Gbyte address space. It had 24-bit FAR pointers in a segmented address space, where each offset addressed 64K bytes (the same as a NEAR pointer), and the segment register allowed a segment to start on any 256 byte boundary in memory, giving the 1 MByte of address space.

                        – jamesqf
                        May 20 at 4:42












                      • @jamesqf The segment registers on x86 are 16 bits wide, not 8 bits. So a 16-bit far pointer is 32 bits in size. In "real mode" (8086) segments can be aligned on any 16-byte boundary. And the segmented addresses 0x7C0:0 and 0x0:7C00 point to the same byte in RAM but they have a different meaning when being used as code pointers.

                        – Martin Rosenau
                        May 20 at 19:41












                      • @Martin Rosenau: Yes. Maybe my comment wasn't clear: the segment:offset register pair occupies 32 bits, but because of the way they're implemented, they only allow for a 24-bit address space. (And if memory serves, you had to manipulate segment & offset registers separately at the assembly level.)

                        – jamesqf
                        May 21 at 20:21











                      • @jamesqf It depends. In "real mode" (8086 mode) (2^20)+(2^16)-16 data bytes can be accessed in memory. This means that there are effectively less than 21 address bits. Hypothetically, an 8086 has 2^32 addresses for code that cannot be substituted. This means that every of these 2^32 addresses has a different meaning and cannot be replaced by another address! This means that code pointers are really effectively 32-bits wide on a 8086. 16-bit code running on a 80386 can address more than 2^29 data bytes, so the effective address width is 30 bits using 16:16 segmented addressing.

                        – Martin Rosenau
                        May 21 at 21:15














                      4












                      4








                      4








                      It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits?




                      If you look at all types of CPUs (including microcontrollers) currently being produced, I would say no.



                      Extreme counterexamples would be architectures where two different pointer sizes are used in the same program:



                      x86, 16-bit



                      In MS-DOS and 16-bit Windows, a "normal" program used both 16- and 32-bit pointers.



                      x86, 32-bit segmented



                      There were only a few, less known operating systems using this memory model.



                      Programs typically used both 32- and 48-bit pointers.



                      STM8A



                      This modern automotive 8-bit CPU uses 16- and 24-bit pointers. Both in the same program, of course.



                      AVR tiny series



                      RAM is addressed using 8-bit pointers, Flash is addressed using 16-bit pointers.



                      (However, AVR tiny cannot be programmed with C++, as far as I know.)






                      share|improve this answer
















                      It is reasonable to assume that in general sizes of pointers of any type (including pointers to functions) are equal to the target architecture bits?




                      If you look at all types of CPUs (including microcontrollers) currently being produced, I would say no.



                      Extreme counterexamples would be architectures where two different pointer sizes are used in the same program:



                      x86, 16-bit



                      In MS-DOS and 16-bit Windows, a "normal" program used both 16- and 32-bit pointers.



                      x86, 32-bit segmented



                      There were only a few, less known operating systems using this memory model.



                      Programs typically used both 32- and 48-bit pointers.



                      STM8A



                      This modern automotive 8-bit CPU uses 16- and 24-bit pointers. Both in the same program, of course.



                      AVR tiny series



                      RAM is addressed using 8-bit pointers, Flash is addressed using 16-bit pointers.



                      (However, AVR tiny cannot be programmed with C++, as far as I know.)







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited May 19 at 19:03

























                      answered May 19 at 18:57









                      Martin RosenauMartin Rosenau

                      9,7681922




                      9,7681922












                      • GCC has an AVR back-end; I assume you can at least compile a function using std:: algorithms, if not containers that do dynamic allocation.

                        – Peter Cordes
                        May 19 at 21:20











                      • If I'm remembering correctly, the 8086 didn't really have 32-bit pointers, which would have allowed a 4 Gbyte address space. It had 24-bit FAR pointers in a segmented address space, where each offset addressed 64K bytes (the same as a NEAR pointer), and the segment register allowed a segment to start on any 256 byte boundary in memory, giving the 1 MByte of address space.

                        – jamesqf
                        May 20 at 4:42












                      • @jamesqf The segment registers on x86 are 16 bits wide, not 8 bits. So a 16-bit far pointer is 32 bits in size. In "real mode" (8086) segments can be aligned on any 16-byte boundary. And the segmented addresses 0x7C0:0 and 0x0:7C00 point to the same byte in RAM but they have a different meaning when being used as code pointers.

                        – Martin Rosenau
                        May 20 at 19:41












                      • @Martin Rosenau: Yes. Maybe my comment wasn't clear: the segment:offset register pair occupies 32 bits, but because of the way they're implemented, they only allow for a 24-bit address space. (And if memory serves, you had to manipulate segment & offset registers separately at the assembly level.)

                        – jamesqf
                        May 21 at 20:21











                      • @jamesqf It depends. In "real mode" (8086 mode) (2^20)+(2^16)-16 data bytes can be accessed in memory. This means that there are effectively less than 21 address bits. Hypothetically, an 8086 has 2^32 addresses for code that cannot be substituted. This means that every of these 2^32 addresses has a different meaning and cannot be replaced by another address! This means that code pointers are really effectively 32-bits wide on a 8086. 16-bit code running on a 80386 can address more than 2^29 data bytes, so the effective address width is 30 bits using 16:16 segmented addressing.

                        – Martin Rosenau
                        May 21 at 21:15


















                      • GCC has an AVR back-end; I assume you can at least compile a function using std:: algorithms, if not containers that do dynamic allocation.

                        – Peter Cordes
                        May 19 at 21:20











                      • If I'm remembering correctly, the 8086 didn't really have 32-bit pointers, which would have allowed a 4 Gbyte address space. It had 24-bit FAR pointers in a segmented address space, where each offset addressed 64K bytes (the same as a NEAR pointer), and the segment register allowed a segment to start on any 256 byte boundary in memory, giving the 1 MByte of address space.

                        – jamesqf
                        May 20 at 4:42












                      • @jamesqf The segment registers on x86 are 16 bits wide, not 8 bits. So a 16-bit far pointer is 32 bits in size. In "real mode" (8086) segments can be aligned on any 16-byte boundary. And the segmented addresses 0x7C0:0 and 0x0:7C00 point to the same byte in RAM but they have a different meaning when being used as code pointers.

                        – Martin Rosenau
                        May 20 at 19:41












                      • @Martin Rosenau: Yes. Maybe my comment wasn't clear: the segment:offset register pair occupies 32 bits, but because of the way they're implemented, they only allow for a 24-bit address space. (And if memory serves, you had to manipulate segment & offset registers separately at the assembly level.)

                        – jamesqf
                        May 21 at 20:21











                      • @jamesqf It depends. In "real mode" (8086 mode) (2^20)+(2^16)-16 data bytes can be accessed in memory. This means that there are effectively less than 21 address bits. Hypothetically, an 8086 has 2^32 addresses for code that cannot be substituted. This means that every of these 2^32 addresses has a different meaning and cannot be replaced by another address! This means that code pointers are really effectively 32-bits wide on a 8086. 16-bit code running on a 80386 can address more than 2^29 data bytes, so the effective address width is 30 bits using 16:16 segmented addressing.

                        – Martin Rosenau
                        May 21 at 21:15

















                      GCC has an AVR back-end; I assume you can at least compile a function using std:: algorithms, if not containers that do dynamic allocation.

                      – Peter Cordes
                      May 19 at 21:20





                      GCC has an AVR back-end; I assume you can at least compile a function using std:: algorithms, if not containers that do dynamic allocation.

                      – Peter Cordes
                      May 19 at 21:20













                      If I'm remembering correctly, the 8086 didn't really have 32-bit pointers, which would have allowed a 4 Gbyte address space. It had 24-bit FAR pointers in a segmented address space, where each offset addressed 64K bytes (the same as a NEAR pointer), and the segment register allowed a segment to start on any 256 byte boundary in memory, giving the 1 MByte of address space.

                      – jamesqf
                      May 20 at 4:42






                      If I'm remembering correctly, the 8086 didn't really have 32-bit pointers, which would have allowed a 4 Gbyte address space. It had 24-bit FAR pointers in a segmented address space, where each offset addressed 64K bytes (the same as a NEAR pointer), and the segment register allowed a segment to start on any 256 byte boundary in memory, giving the 1 MByte of address space.

                      – jamesqf
                      May 20 at 4:42














                      @jamesqf The segment registers on x86 are 16 bits wide, not 8 bits. So a 16-bit far pointer is 32 bits in size. In "real mode" (8086) segments can be aligned on any 16-byte boundary. And the segmented addresses 0x7C0:0 and 0x0:7C00 point to the same byte in RAM but they have a different meaning when being used as code pointers.

                      – Martin Rosenau
                      May 20 at 19:41






                      @jamesqf The segment registers on x86 are 16 bits wide, not 8 bits. So a 16-bit far pointer is 32 bits in size. In "real mode" (8086) segments can be aligned on any 16-byte boundary. And the segmented addresses 0x7C0:0 and 0x0:7C00 point to the same byte in RAM but they have a different meaning when being used as code pointers.

                      – Martin Rosenau
                      May 20 at 19:41














                      @Martin Rosenau: Yes. Maybe my comment wasn't clear: the segment:offset register pair occupies 32 bits, but because of the way they're implemented, they only allow for a 24-bit address space. (And if memory serves, you had to manipulate segment & offset registers separately at the assembly level.)

                      – jamesqf
                      May 21 at 20:21





                      @Martin Rosenau: Yes. Maybe my comment wasn't clear: the segment:offset register pair occupies 32 bits, but because of the way they're implemented, they only allow for a 24-bit address space. (And if memory serves, you had to manipulate segment & offset registers separately at the assembly level.)

                      – jamesqf
                      May 21 at 20:21













                      @jamesqf It depends. In "real mode" (8086 mode) (2^20)+(2^16)-16 data bytes can be accessed in memory. This means that there are effectively less than 21 address bits. Hypothetically, an 8086 has 2^32 addresses for code that cannot be substituted. This means that every of these 2^32 addresses has a different meaning and cannot be replaced by another address! This means that code pointers are really effectively 32-bits wide on a 8086. 16-bit code running on a 80386 can address more than 2^29 data bytes, so the effective address width is 30 bits using 16:16 segmented addressing.

                      – Martin Rosenau
                      May 21 at 21:15






                      @jamesqf It depends. In "real mode" (8086 mode) (2^20)+(2^16)-16 data bytes can be accessed in memory. This means that there are effectively less than 21 address bits. Hypothetically, an 8086 has 2^32 addresses for code that cannot be substituted. This means that every of these 2^32 addresses has a different meaning and cannot be replaced by another address! This means that code pointers are really effectively 32-bits wide on a 8086. 16-bit code running on a 80386 can address more than 2^29 data bytes, so the effective address width is 30 bits using 16:16 segmented addressing.

                      – Martin Rosenau
                      May 21 at 21:15












                      3














                      It's not correct, for example DOS pointers (16 bit) can be far (seg+ofs).



                      However, for the usual targets (Windows, OSX, Linux, Android, iOS) then it's correct. Because they all use the flat programming model which relies on paging.



                      In theory, you can also have systems which uses only the lower 32 bits when in x64. An example is a Windows executable linked without LARGEADDRESSAWARE. However this is to help the programmer avoid bugs when switching to x64. The pointers are truncated to 32 bits, but they are still 64 bit.



                      In x64 operating systems then this assumption is always true, because the flat mode is the only valid one. Long mode in CPU forces GDT entries to be 64 bit flat.



                      One also mentions a x32 ABI, I believe it is based on the same paging technology, forcing all pointers to be mapped to the lower 4gb. However this must be based to the same theory as in Windows. In x64 you can only have flat mode.



                      In 32 bit protected mode you could have pointers up to 48 bits. (Segmented mode). You can also have callgates. But, no operating system uses that mode.






                      share|improve this answer




















                      • 2





                        x86 32-bit protected mode is used by every 32-bit x86 OS. But (almost?) all of them use a flat memory model, which I think is the point you're making. Anyway yes, a seg:off "far" pointer would take 6 bytes in protected mode, but you still only have 4GB of actual addressable memory. Segment base + offset produces a 32-bit linear address. With paging disabled it's a 32-bit physical address. With paging enabled, it's a 32-bit virtual address. PAE can let separate processes each use a separate 4GB of physical memory at the same time by translating 32-bit virtual to 36-bit physical addresses.

                        – Peter Cordes
                        May 19 at 16:03






                      • 1





                        The Linux x32 ABI and other ILP32 ABIs in general don't necessarily require paging. You could in theory have an OS that loads position-independent code at different physical addresses within the low 32 bits of physical address space.

                        – Peter Cordes
                        May 19 at 16:05











                      • Nitpick: long mode ignores the base/limit in GDT entries selected by segments other than FS/GS, rather than requiring them to be 0 / -1. And "mapped" is the wrong word for ensuring all pointers are in the low 4GB, that phrasing seems to imply arbitrary virtual addresses mapped to the low 4GB of physical memory. (And BTW, it's actually the low 2GB of virtual address space, so zero- and sign- extension of 32-bit absolute pointers are both valid. e.g. mov edi, array (zero-extended immediate) or add rax, [array + rcx] (sign extended disp32) can both be used for static addresses.

                        – Peter Cordes
                        May 19 at 16:25















                      3














                      It's not correct, for example DOS pointers (16 bit) can be far (seg+ofs).



                      However, for the usual targets (Windows, OSX, Linux, Android, iOS) then it's correct. Because they all use the flat programming model which relies on paging.



                      In theory, you can also have systems which uses only the lower 32 bits when in x64. An example is a Windows executable linked without LARGEADDRESSAWARE. However this is to help the programmer avoid bugs when switching to x64. The pointers are truncated to 32 bits, but they are still 64 bit.



                      In x64 operating systems then this assumption is always true, because the flat mode is the only valid one. Long mode in CPU forces GDT entries to be 64 bit flat.



                      One also mentions a x32 ABI, I believe it is based on the same paging technology, forcing all pointers to be mapped to the lower 4gb. However this must be based to the same theory as in Windows. In x64 you can only have flat mode.



                      In 32 bit protected mode you could have pointers up to 48 bits. (Segmented mode). You can also have callgates. But, no operating system uses that mode.






                      share|improve this answer




















                      • 2





                        x86 32-bit protected mode is used by every 32-bit x86 OS. But (almost?) all of them use a flat memory model, which I think is the point you're making. Anyway yes, a seg:off "far" pointer would take 6 bytes in protected mode, but you still only have 4GB of actual addressable memory. Segment base + offset produces a 32-bit linear address. With paging disabled it's a 32-bit physical address. With paging enabled, it's a 32-bit virtual address. PAE can let separate processes each use a separate 4GB of physical memory at the same time by translating 32-bit virtual to 36-bit physical addresses.

                        – Peter Cordes
                        May 19 at 16:03






                      • 1





                        The Linux x32 ABI and other ILP32 ABIs in general don't necessarily require paging. You could in theory have an OS that loads position-independent code at different physical addresses within the low 32 bits of physical address space.

                        – Peter Cordes
                        May 19 at 16:05











                      • Nitpick: long mode ignores the base/limit in GDT entries selected by segments other than FS/GS, rather than requiring them to be 0 / -1. And "mapped" is the wrong word for ensuring all pointers are in the low 4GB, that phrasing seems to imply arbitrary virtual addresses mapped to the low 4GB of physical memory. (And BTW, it's actually the low 2GB of virtual address space, so zero- and sign- extension of 32-bit absolute pointers are both valid. e.g. mov edi, array (zero-extended immediate) or add rax, [array + rcx] (sign extended disp32) can both be used for static addresses.

                        – Peter Cordes
                        May 19 at 16:25













                      3












                      3








                      3







                      It's not correct, for example DOS pointers (16 bit) can be far (seg+ofs).



                      However, for the usual targets (Windows, OSX, Linux, Android, iOS) then it's correct. Because they all use the flat programming model which relies on paging.



                      In theory, you can also have systems which uses only the lower 32 bits when in x64. An example is a Windows executable linked without LARGEADDRESSAWARE. However this is to help the programmer avoid bugs when switching to x64. The pointers are truncated to 32 bits, but they are still 64 bit.



                      In x64 operating systems then this assumption is always true, because the flat mode is the only valid one. Long mode in CPU forces GDT entries to be 64 bit flat.



                      One also mentions a x32 ABI, I believe it is based on the same paging technology, forcing all pointers to be mapped to the lower 4gb. However this must be based to the same theory as in Windows. In x64 you can only have flat mode.



                      In 32 bit protected mode you could have pointers up to 48 bits. (Segmented mode). You can also have callgates. But, no operating system uses that mode.






                      share|improve this answer















                      It's not correct, for example DOS pointers (16 bit) can be far (seg+ofs).



                      However, for the usual targets (Windows, OSX, Linux, Android, iOS) then it's correct. Because they all use the flat programming model which relies on paging.



                      In theory, you can also have systems which uses only the lower 32 bits when in x64. An example is a Windows executable linked without LARGEADDRESSAWARE. However this is to help the programmer avoid bugs when switching to x64. The pointers are truncated to 32 bits, but they are still 64 bit.



                      In x64 operating systems then this assumption is always true, because the flat mode is the only valid one. Long mode in CPU forces GDT entries to be 64 bit flat.



                      One also mentions a x32 ABI, I believe it is based on the same paging technology, forcing all pointers to be mapped to the lower 4gb. However this must be based to the same theory as in Windows. In x64 you can only have flat mode.



                      In 32 bit protected mode you could have pointers up to 48 bits. (Segmented mode). You can also have callgates. But, no operating system uses that mode.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited May 19 at 15:22

























                      answered May 19 at 15:11









                      Michael ChourdakisMichael Chourdakis

                      3,14812040




                      3,14812040







                      • 2





                        x86 32-bit protected mode is used by every 32-bit x86 OS. But (almost?) all of them use a flat memory model, which I think is the point you're making. Anyway yes, a seg:off "far" pointer would take 6 bytes in protected mode, but you still only have 4GB of actual addressable memory. Segment base + offset produces a 32-bit linear address. With paging disabled it's a 32-bit physical address. With paging enabled, it's a 32-bit virtual address. PAE can let separate processes each use a separate 4GB of physical memory at the same time by translating 32-bit virtual to 36-bit physical addresses.

                        – Peter Cordes
                        May 19 at 16:03






                      • 1





                        The Linux x32 ABI and other ILP32 ABIs in general don't necessarily require paging. You could in theory have an OS that loads position-independent code at different physical addresses within the low 32 bits of physical address space.

                        – Peter Cordes
                        May 19 at 16:05











                      • Nitpick: long mode ignores the base/limit in GDT entries selected by segments other than FS/GS, rather than requiring them to be 0 / -1. And "mapped" is the wrong word for ensuring all pointers are in the low 4GB, that phrasing seems to imply arbitrary virtual addresses mapped to the low 4GB of physical memory. (And BTW, it's actually the low 2GB of virtual address space, so zero- and sign- extension of 32-bit absolute pointers are both valid. e.g. mov edi, array (zero-extended immediate) or add rax, [array + rcx] (sign extended disp32) can both be used for static addresses.

                        – Peter Cordes
                        May 19 at 16:25












                      • 2





                        x86 32-bit protected mode is used by every 32-bit x86 OS. But (almost?) all of them use a flat memory model, which I think is the point you're making. Anyway yes, a seg:off "far" pointer would take 6 bytes in protected mode, but you still only have 4GB of actual addressable memory. Segment base + offset produces a 32-bit linear address. With paging disabled it's a 32-bit physical address. With paging enabled, it's a 32-bit virtual address. PAE can let separate processes each use a separate 4GB of physical memory at the same time by translating 32-bit virtual to 36-bit physical addresses.

                        – Peter Cordes
                        May 19 at 16:03






                      • 1





                        The Linux x32 ABI and other ILP32 ABIs in general don't necessarily require paging. You could in theory have an OS that loads position-independent code at different physical addresses within the low 32 bits of physical address space.

                        – Peter Cordes
                        May 19 at 16:05











                      • Nitpick: long mode ignores the base/limit in GDT entries selected by segments other than FS/GS, rather than requiring them to be 0 / -1. And "mapped" is the wrong word for ensuring all pointers are in the low 4GB, that phrasing seems to imply arbitrary virtual addresses mapped to the low 4GB of physical memory. (And BTW, it's actually the low 2GB of virtual address space, so zero- and sign- extension of 32-bit absolute pointers are both valid. e.g. mov edi, array (zero-extended immediate) or add rax, [array + rcx] (sign extended disp32) can both be used for static addresses.

                        – Peter Cordes
                        May 19 at 16:25







                      2




                      2





                      x86 32-bit protected mode is used by every 32-bit x86 OS. But (almost?) all of them use a flat memory model, which I think is the point you're making. Anyway yes, a seg:off "far" pointer would take 6 bytes in protected mode, but you still only have 4GB of actual addressable memory. Segment base + offset produces a 32-bit linear address. With paging disabled it's a 32-bit physical address. With paging enabled, it's a 32-bit virtual address. PAE can let separate processes each use a separate 4GB of physical memory at the same time by translating 32-bit virtual to 36-bit physical addresses.

                      – Peter Cordes
                      May 19 at 16:03





                      x86 32-bit protected mode is used by every 32-bit x86 OS. But (almost?) all of them use a flat memory model, which I think is the point you're making. Anyway yes, a seg:off "far" pointer would take 6 bytes in protected mode, but you still only have 4GB of actual addressable memory. Segment base + offset produces a 32-bit linear address. With paging disabled it's a 32-bit physical address. With paging enabled, it's a 32-bit virtual address. PAE can let separate processes each use a separate 4GB of physical memory at the same time by translating 32-bit virtual to 36-bit physical addresses.

                      – Peter Cordes
                      May 19 at 16:03




                      1




                      1





                      The Linux x32 ABI and other ILP32 ABIs in general don't necessarily require paging. You could in theory have an OS that loads position-independent code at different physical addresses within the low 32 bits of physical address space.

                      – Peter Cordes
                      May 19 at 16:05





                      The Linux x32 ABI and other ILP32 ABIs in general don't necessarily require paging. You could in theory have an OS that loads position-independent code at different physical addresses within the low 32 bits of physical address space.

                      – Peter Cordes
                      May 19 at 16:05













                      Nitpick: long mode ignores the base/limit in GDT entries selected by segments other than FS/GS, rather than requiring them to be 0 / -1. And "mapped" is the wrong word for ensuring all pointers are in the low 4GB, that phrasing seems to imply arbitrary virtual addresses mapped to the low 4GB of physical memory. (And BTW, it's actually the low 2GB of virtual address space, so zero- and sign- extension of 32-bit absolute pointers are both valid. e.g. mov edi, array (zero-extended immediate) or add rax, [array + rcx] (sign extended disp32) can both be used for static addresses.

                      – Peter Cordes
                      May 19 at 16:25





                      Nitpick: long mode ignores the base/limit in GDT entries selected by segments other than FS/GS, rather than requiring them to be 0 / -1. And "mapped" is the wrong word for ensuring all pointers are in the low 4GB, that phrasing seems to imply arbitrary virtual addresses mapped to the low 4GB of physical memory. (And BTW, it's actually the low 2GB of virtual address space, so zero- and sign- extension of 32-bit absolute pointers are both valid. e.g. mov edi, array (zero-extended immediate) or add rax, [array + rcx] (sign extended disp32) can both be used for static addresses.

                      – Peter Cordes
                      May 19 at 16:25











                      3














                      For correctness, you cannot assume anything. You have to check and be prepared to deal with weird situations.



                      As a general rule of thumb, it is a reasonable default assumption.



                      It's not universally true though. See the X32 ABI, for example, which uses 32bit pointers on 64bit architectures to save a bit of memory and cache footprint. Same for the ILP32 ABI on AArch64.



                      So, for guesstimating memory use, you can use your assumption and it will often be right.






                      share|improve this answer




















                      • 2





                        PAE isn't relevant to C++ programming on any existing C++ implementation. It doesn't increase the size of virtual address space, only physical. And it only works when paging is enabled, so in a hypothetical freestanding C++ program that runs with paging disabled it's no help in addressing more than 4GB of physical memory.

                        – Peter Cordes
                        May 19 at 15:52












                      • @PeterCordes - Good point. Removed

                        – Jesper Juhl
                        May 19 at 15:55











                      • @JesperJuhl There are way too many architectures (e.g., base & displacement pointers) and language systems (e.g. LISP) where pointers to different types are of different lengths. If you include pointers-to-functions, as OP explicitly did, There are several cases where the size of the pointer depends on the number of paramaters passed and the return value of the function. This is a bad assumption for any portability intention, and can get you in deep before you realize the problems. Your answer's last two sentences should be the first two.

                        – mpez0
                        May 19 at 16:08







                      • 1





                        @mpez0 I know. And yes, of course it's a bad assumption for portability, which is why I explicitly said that it was an ok assumption for guesstimating memory use, but useless for correctness.

                        – Jesper Juhl
                        May 19 at 16:10











                      • @mpez0 - "Your answer's last two sentences should be the first two" - better now?

                        – Jesper Juhl
                        May 21 at 17:40















                      3














                      For correctness, you cannot assume anything. You have to check and be prepared to deal with weird situations.



                      As a general rule of thumb, it is a reasonable default assumption.



                      It's not universally true though. See the X32 ABI, for example, which uses 32bit pointers on 64bit architectures to save a bit of memory and cache footprint. Same for the ILP32 ABI on AArch64.



                      So, for guesstimating memory use, you can use your assumption and it will often be right.






                      share|improve this answer




















                      • 2





                        PAE isn't relevant to C++ programming on any existing C++ implementation. It doesn't increase the size of virtual address space, only physical. And it only works when paging is enabled, so in a hypothetical freestanding C++ program that runs with paging disabled it's no help in addressing more than 4GB of physical memory.

                        – Peter Cordes
                        May 19 at 15:52












                      • @PeterCordes - Good point. Removed

                        – Jesper Juhl
                        May 19 at 15:55











                      • @JesperJuhl There are way too many architectures (e.g., base & displacement pointers) and language systems (e.g. LISP) where pointers to different types are of different lengths. If you include pointers-to-functions, as OP explicitly did, There are several cases where the size of the pointer depends on the number of paramaters passed and the return value of the function. This is a bad assumption for any portability intention, and can get you in deep before you realize the problems. Your answer's last two sentences should be the first two.

                        – mpez0
                        May 19 at 16:08







                      • 1





                        @mpez0 I know. And yes, of course it's a bad assumption for portability, which is why I explicitly said that it was an ok assumption for guesstimating memory use, but useless for correctness.

                        – Jesper Juhl
                        May 19 at 16:10











                      • @mpez0 - "Your answer's last two sentences should be the first two" - better now?

                        – Jesper Juhl
                        May 21 at 17:40













                      3












                      3








                      3







                      For correctness, you cannot assume anything. You have to check and be prepared to deal with weird situations.



                      As a general rule of thumb, it is a reasonable default assumption.



                      It's not universally true though. See the X32 ABI, for example, which uses 32bit pointers on 64bit architectures to save a bit of memory and cache footprint. Same for the ILP32 ABI on AArch64.



                      So, for guesstimating memory use, you can use your assumption and it will often be right.






                      share|improve this answer















                      For correctness, you cannot assume anything. You have to check and be prepared to deal with weird situations.



                      As a general rule of thumb, it is a reasonable default assumption.



                      It's not universally true though. See the X32 ABI, for example, which uses 32bit pointers on 64bit architectures to save a bit of memory and cache footprint. Same for the ILP32 ABI on AArch64.



                      So, for guesstimating memory use, you can use your assumption and it will often be right.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited May 21 at 17:40

























                      answered May 19 at 14:46









                      Jesper JuhlJesper Juhl

                      19k32751




                      19k32751







                      • 2





                        PAE isn't relevant to C++ programming on any existing C++ implementation. It doesn't increase the size of virtual address space, only physical. And it only works when paging is enabled, so in a hypothetical freestanding C++ program that runs with paging disabled it's no help in addressing more than 4GB of physical memory.

                        – Peter Cordes
                        May 19 at 15:52












                      • @PeterCordes - Good point. Removed

                        – Jesper Juhl
                        May 19 at 15:55











                      • @JesperJuhl There are way too many architectures (e.g., base & displacement pointers) and language systems (e.g. LISP) where pointers to different types are of different lengths. If you include pointers-to-functions, as OP explicitly did, There are several cases where the size of the pointer depends on the number of paramaters passed and the return value of the function. This is a bad assumption for any portability intention, and can get you in deep before you realize the problems. Your answer's last two sentences should be the first two.

                        – mpez0
                        May 19 at 16:08







                      • 1





                        @mpez0 I know. And yes, of course it's a bad assumption for portability, which is why I explicitly said that it was an ok assumption for guesstimating memory use, but useless for correctness.

                        – Jesper Juhl
                        May 19 at 16:10











                      • @mpez0 - "Your answer's last two sentences should be the first two" - better now?

                        – Jesper Juhl
                        May 21 at 17:40












                      • 2





                        PAE isn't relevant to C++ programming on any existing C++ implementation. It doesn't increase the size of virtual address space, only physical. And it only works when paging is enabled, so in a hypothetical freestanding C++ program that runs with paging disabled it's no help in addressing more than 4GB of physical memory.

                        – Peter Cordes
                        May 19 at 15:52












                      • @PeterCordes - Good point. Removed

                        – Jesper Juhl
                        May 19 at 15:55











                      • @JesperJuhl There are way too many architectures (e.g., base & displacement pointers) and language systems (e.g. LISP) where pointers to different types are of different lengths. If you include pointers-to-functions, as OP explicitly did, There are several cases where the size of the pointer depends on the number of paramaters passed and the return value of the function. This is a bad assumption for any portability intention, and can get you in deep before you realize the problems. Your answer's last two sentences should be the first two.

                        – mpez0
                        May 19 at 16:08







                      • 1





                        @mpez0 I know. And yes, of course it's a bad assumption for portability, which is why I explicitly said that it was an ok assumption for guesstimating memory use, but useless for correctness.

                        – Jesper Juhl
                        May 19 at 16:10











                      • @mpez0 - "Your answer's last two sentences should be the first two" - better now?

                        – Jesper Juhl
                        May 21 at 17:40







                      2




                      2





                      PAE isn't relevant to C++ programming on any existing C++ implementation. It doesn't increase the size of virtual address space, only physical. And it only works when paging is enabled, so in a hypothetical freestanding C++ program that runs with paging disabled it's no help in addressing more than 4GB of physical memory.

                      – Peter Cordes
                      May 19 at 15:52






                      PAE isn't relevant to C++ programming on any existing C++ implementation. It doesn't increase the size of virtual address space, only physical. And it only works when paging is enabled, so in a hypothetical freestanding C++ program that runs with paging disabled it's no help in addressing more than 4GB of physical memory.

                      – Peter Cordes
                      May 19 at 15:52














                      @PeterCordes - Good point. Removed

                      – Jesper Juhl
                      May 19 at 15:55





                      @PeterCordes - Good point. Removed

                      – Jesper Juhl
                      May 19 at 15:55













                      @JesperJuhl There are way too many architectures (e.g., base & displacement pointers) and language systems (e.g. LISP) where pointers to different types are of different lengths. If you include pointers-to-functions, as OP explicitly did, There are several cases where the size of the pointer depends on the number of paramaters passed and the return value of the function. This is a bad assumption for any portability intention, and can get you in deep before you realize the problems. Your answer's last two sentences should be the first two.

                      – mpez0
                      May 19 at 16:08






                      @JesperJuhl There are way too many architectures (e.g., base & displacement pointers) and language systems (e.g. LISP) where pointers to different types are of different lengths. If you include pointers-to-functions, as OP explicitly did, There are several cases where the size of the pointer depends on the number of paramaters passed and the return value of the function. This is a bad assumption for any portability intention, and can get you in deep before you realize the problems. Your answer's last two sentences should be the first two.

                      – mpez0
                      May 19 at 16:08





                      1




                      1





                      @mpez0 I know. And yes, of course it's a bad assumption for portability, which is why I explicitly said that it was an ok assumption for guesstimating memory use, but useless for correctness.

                      – Jesper Juhl
                      May 19 at 16:10





                      @mpez0 I know. And yes, of course it's a bad assumption for portability, which is why I explicitly said that it was an ok assumption for guesstimating memory use, but useless for correctness.

                      – Jesper Juhl
                      May 19 at 16:10













                      @mpez0 - "Your answer's last two sentences should be the first two" - better now?

                      – Jesper Juhl
                      May 21 at 17:40





                      @mpez0 - "Your answer's last two sentences should be the first two" - better now?

                      – Jesper Juhl
                      May 21 at 17:40











                      1














                      Historically, on microcomputers and microcontrollers, pointers were often wider than general-purpose registers so that the CPU could address enough memory and still fit within the transistor budget. Most 8-bit CPUs (such as the 8080, Z80 or 6502) had 16-bit addresses.



                      Today, a mismatch is more likely to be because an app doesn’t need multiple gigabytes of data, so saving four bytes of memory on every pointer is a win.



                      Both C and C++ provide separate size_t, uintptr_t and off_t types, representing the largest possible object size (which might be smaller than the size of a pointer if the memory model is not flat), an integral type wide enough to hold a pointer, and a file offset (often wider than the largest object allowed in memory), respectively. A size_t (unsigned) or ptrdiff_t (signed) is the most portable way to get the native word size. Additionally, POSIX guarantees that the system compiler has some flag that means a long can hold any of these, but you cannot always assume so.






                      share|improve this answer




















                      • 1





                        Any reason you left out signed intptr_t? Anyway, worth pointing out that [u]intptr_t can hold any pointer, while size_t only has to hold the max object size. On a machine without a flat memory model, these can easily be different widths. e.g. on x86-16 with far pointers being possible, uintptr_t has to be 32-bit, but size_t can be 16-bit.

                        – Peter Cordes
                        May 20 at 0:19






                      • 1





                        (Note that most implementations restrict object size to SIZE_MAX/2 or less, so ptrdiff_t can't overflow with char arrays.) Why is the maximum size of an array "too large"?

                        – Peter Cordes
                        May 20 at 0:27











                      • off_t is for file sizes / positions. It can be and often is 64-bit on a purely 32-bit system, and mentioning it here makes zero sense. Also, none of the types you mentioned are guaranteed to find the max register width, though: a modern ILP32 ABI on a 64-bit architecture will typically have 32-bit size_t, uintptr_t, and ptrdiff_t. So if you use that to decide if the machine has efficient long long / uint64_t, you'll incorrectly rule out x32 on x86-64 and ILP32 on AArch64, for example. You could additionally check #ifdef __SIZEOF_INT128__ because GCC defines that on 64-bit.

                        – Peter Cordes
                        May 20 at 0:27












                      • @PeterCordes I don’t think we disagree. I mentioned only uintptr_t because it’s exactly the same width as the signed counterpart, and the other two types are unsigned.

                        – Davislor
                        May 20 at 0:57











                      • @PeterCordes uintptr_t doesn't have to be anything, it is an optional type

                        – M.M
                        May 20 at 1:50















                      1














                      Historically, on microcomputers and microcontrollers, pointers were often wider than general-purpose registers so that the CPU could address enough memory and still fit within the transistor budget. Most 8-bit CPUs (such as the 8080, Z80 or 6502) had 16-bit addresses.



                      Today, a mismatch is more likely to be because an app doesn’t need multiple gigabytes of data, so saving four bytes of memory on every pointer is a win.



                      Both C and C++ provide separate size_t, uintptr_t and off_t types, representing the largest possible object size (which might be smaller than the size of a pointer if the memory model is not flat), an integral type wide enough to hold a pointer, and a file offset (often wider than the largest object allowed in memory), respectively. A size_t (unsigned) or ptrdiff_t (signed) is the most portable way to get the native word size. Additionally, POSIX guarantees that the system compiler has some flag that means a long can hold any of these, but you cannot always assume so.






                      share|improve this answer




















                      • 1





                        Any reason you left out signed intptr_t? Anyway, worth pointing out that [u]intptr_t can hold any pointer, while size_t only has to hold the max object size. On a machine without a flat memory model, these can easily be different widths. e.g. on x86-16 with far pointers being possible, uintptr_t has to be 32-bit, but size_t can be 16-bit.

                        – Peter Cordes
                        May 20 at 0:19






                      • 1





                        (Note that most implementations restrict object size to SIZE_MAX/2 or less, so ptrdiff_t can't overflow with char arrays.) Why is the maximum size of an array "too large"?

                        – Peter Cordes
                        May 20 at 0:27











                      • off_t is for file sizes / positions. It can be and often is 64-bit on a purely 32-bit system, and mentioning it here makes zero sense. Also, none of the types you mentioned are guaranteed to find the max register width, though: a modern ILP32 ABI on a 64-bit architecture will typically have 32-bit size_t, uintptr_t, and ptrdiff_t. So if you use that to decide if the machine has efficient long long / uint64_t, you'll incorrectly rule out x32 on x86-64 and ILP32 on AArch64, for example. You could additionally check #ifdef __SIZEOF_INT128__ because GCC defines that on 64-bit.

                        – Peter Cordes
                        May 20 at 0:27












                      • @PeterCordes I don’t think we disagree. I mentioned only uintptr_t because it’s exactly the same width as the signed counterpart, and the other two types are unsigned.

                        – Davislor
                        May 20 at 0:57











                      • @PeterCordes uintptr_t doesn't have to be anything, it is an optional type

                        – M.M
                        May 20 at 1:50













                      1












                      1








                      1







                      Historically, on microcomputers and microcontrollers, pointers were often wider than general-purpose registers so that the CPU could address enough memory and still fit within the transistor budget. Most 8-bit CPUs (such as the 8080, Z80 or 6502) had 16-bit addresses.



                      Today, a mismatch is more likely to be because an app doesn’t need multiple gigabytes of data, so saving four bytes of memory on every pointer is a win.



                      Both C and C++ provide separate size_t, uintptr_t and off_t types, representing the largest possible object size (which might be smaller than the size of a pointer if the memory model is not flat), an integral type wide enough to hold a pointer, and a file offset (often wider than the largest object allowed in memory), respectively. A size_t (unsigned) or ptrdiff_t (signed) is the most portable way to get the native word size. Additionally, POSIX guarantees that the system compiler has some flag that means a long can hold any of these, but you cannot always assume so.






                      share|improve this answer















                      Historically, on microcomputers and microcontrollers, pointers were often wider than general-purpose registers so that the CPU could address enough memory and still fit within the transistor budget. Most 8-bit CPUs (such as the 8080, Z80 or 6502) had 16-bit addresses.



                      Today, a mismatch is more likely to be because an app doesn’t need multiple gigabytes of data, so saving four bytes of memory on every pointer is a win.



                      Both C and C++ provide separate size_t, uintptr_t and off_t types, representing the largest possible object size (which might be smaller than the size of a pointer if the memory model is not flat), an integral type wide enough to hold a pointer, and a file offset (often wider than the largest object allowed in memory), respectively. A size_t (unsigned) or ptrdiff_t (signed) is the most portable way to get the native word size. Additionally, POSIX guarantees that the system compiler has some flag that means a long can hold any of these, but you cannot always assume so.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited May 20 at 1:01

























                      answered May 19 at 23:39









                      DavislorDavislor

                      9,27011327




                      9,27011327







                      • 1





                        Any reason you left out signed intptr_t? Anyway, worth pointing out that [u]intptr_t can hold any pointer, while size_t only has to hold the max object size. On a machine without a flat memory model, these can easily be different widths. e.g. on x86-16 with far pointers being possible, uintptr_t has to be 32-bit, but size_t can be 16-bit.

                        – Peter Cordes
                        May 20 at 0:19






                      • 1





                        (Note that most implementations restrict object size to SIZE_MAX/2 or less, so ptrdiff_t can't overflow with char arrays.) Why is the maximum size of an array "too large"?

                        – Peter Cordes
                        May 20 at 0:27











                      • off_t is for file sizes / positions. It can be and often is 64-bit on a purely 32-bit system, and mentioning it here makes zero sense. Also, none of the types you mentioned are guaranteed to find the max register width, though: a modern ILP32 ABI on a 64-bit architecture will typically have 32-bit size_t, uintptr_t, and ptrdiff_t. So if you use that to decide if the machine has efficient long long / uint64_t, you'll incorrectly rule out x32 on x86-64 and ILP32 on AArch64, for example. You could additionally check #ifdef __SIZEOF_INT128__ because GCC defines that on 64-bit.

                        – Peter Cordes
                        May 20 at 0:27












                      • @PeterCordes I don’t think we disagree. I mentioned only uintptr_t because it’s exactly the same width as the signed counterpart, and the other two types are unsigned.

                        – Davislor
                        May 20 at 0:57











                      • @PeterCordes uintptr_t doesn't have to be anything, it is an optional type

                        – M.M
                        May 20 at 1:50












                      • 1





                        Any reason you left out signed intptr_t? Anyway, worth pointing out that [u]intptr_t can hold any pointer, while size_t only has to hold the max object size. On a machine without a flat memory model, these can easily be different widths. e.g. on x86-16 with far pointers being possible, uintptr_t has to be 32-bit, but size_t can be 16-bit.

                        – Peter Cordes
                        May 20 at 0:19






                      • 1





                        (Note that most implementations restrict object size to SIZE_MAX/2 or less, so ptrdiff_t can't overflow with char arrays.) Why is the maximum size of an array "too large"?

                        – Peter Cordes
                        May 20 at 0:27











                      • off_t is for file sizes / positions. It can be and often is 64-bit on a purely 32-bit system, and mentioning it here makes zero sense. Also, none of the types you mentioned are guaranteed to find the max register width, though: a modern ILP32 ABI on a 64-bit architecture will typically have 32-bit size_t, uintptr_t, and ptrdiff_t. So if you use that to decide if the machine has efficient long long / uint64_t, you'll incorrectly rule out x32 on x86-64 and ILP32 on AArch64, for example. You could additionally check #ifdef __SIZEOF_INT128__ because GCC defines that on 64-bit.

                        – Peter Cordes
                        May 20 at 0:27












                      • @PeterCordes I don’t think we disagree. I mentioned only uintptr_t because it’s exactly the same width as the signed counterpart, and the other two types are unsigned.

                        – Davislor
                        May 20 at 0:57











                      • @PeterCordes uintptr_t doesn't have to be anything, it is an optional type

                        – M.M
                        May 20 at 1:50







                      1




                      1





                      Any reason you left out signed intptr_t? Anyway, worth pointing out that [u]intptr_t can hold any pointer, while size_t only has to hold the max object size. On a machine without a flat memory model, these can easily be different widths. e.g. on x86-16 with far pointers being possible, uintptr_t has to be 32-bit, but size_t can be 16-bit.

                      – Peter Cordes
                      May 20 at 0:19





                      Any reason you left out signed intptr_t? Anyway, worth pointing out that [u]intptr_t can hold any pointer, while size_t only has to hold the max object size. On a machine without a flat memory model, these can easily be different widths. e.g. on x86-16 with far pointers being possible, uintptr_t has to be 32-bit, but size_t can be 16-bit.

                      – Peter Cordes
                      May 20 at 0:19




                      1




                      1





                      (Note that most implementations restrict object size to SIZE_MAX/2 or less, so ptrdiff_t can't overflow with char arrays.) Why is the maximum size of an array "too large"?

                      – Peter Cordes
                      May 20 at 0:27





                      (Note that most implementations restrict object size to SIZE_MAX/2 or less, so ptrdiff_t can't overflow with char arrays.) Why is the maximum size of an array "too large"?

                      – Peter Cordes
                      May 20 at 0:27













                      off_t is for file sizes / positions. It can be and often is 64-bit on a purely 32-bit system, and mentioning it here makes zero sense. Also, none of the types you mentioned are guaranteed to find the max register width, though: a modern ILP32 ABI on a 64-bit architecture will typically have 32-bit size_t, uintptr_t, and ptrdiff_t. So if you use that to decide if the machine has efficient long long / uint64_t, you'll incorrectly rule out x32 on x86-64 and ILP32 on AArch64, for example. You could additionally check #ifdef __SIZEOF_INT128__ because GCC defines that on 64-bit.

                      – Peter Cordes
                      May 20 at 0:27






                      off_t is for file sizes / positions. It can be and often is 64-bit on a purely 32-bit system, and mentioning it here makes zero sense. Also, none of the types you mentioned are guaranteed to find the max register width, though: a modern ILP32 ABI on a 64-bit architecture will typically have 32-bit size_t, uintptr_t, and ptrdiff_t. So if you use that to decide if the machine has efficient long long / uint64_t, you'll incorrectly rule out x32 on x86-64 and ILP32 on AArch64, for example. You could additionally check #ifdef __SIZEOF_INT128__ because GCC defines that on 64-bit.

                      – Peter Cordes
                      May 20 at 0:27














                      @PeterCordes I don’t think we disagree. I mentioned only uintptr_t because it’s exactly the same width as the signed counterpart, and the other two types are unsigned.

                      – Davislor
                      May 20 at 0:57





                      @PeterCordes I don’t think we disagree. I mentioned only uintptr_t because it’s exactly the same width as the signed counterpart, and the other two types are unsigned.

                      – Davislor
                      May 20 at 0:57













                      @PeterCordes uintptr_t doesn't have to be anything, it is an optional type

                      – M.M
                      May 20 at 1:50





                      @PeterCordes uintptr_t doesn't have to be anything, it is an optional type

                      – M.M
                      May 20 at 1:50











                      0














                      Generally pointers will be size 2 on a 16-bit system, 3 on a 24-bit system, 4 on a 32-bit system, and 8 on a 64-bit system. It depends on the ABI and C implementation. AMD has long and legacy modes, and there are differences between AMD64 and Intel64 for Assembly language programmers but these are hidden for higher level languages.



                      Any problems with C/C++ code is likely to be due to poor programming practices and ignoring compiler warnings. See: "20 issues of porting C++ code to the 64-bit platform".



                      See also: "Can pointers be of different sizes?" and LRiO's answer:




                      ... you are asking about C++ and its compliant implementations, not some specific physical machine. I'd have to quote the entire standard in order to prove it, but the simple fact is that it makes no guarantees on the result of sizeof(T*) for any T, and (as a corollary) no guarantees that sizeof(T1*) == sizeof(T2*) for any T1 and T2).




                      Note: Where is answered by JeremyP, C99 section 6.3.2.3, subsection 8:




                      A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.




                      In GCC you can avoid incorrect assumptions by using built-in functions: "Object Size Checking Built-in Functions":




                      Built-in Function: size_t __builtin_object_size (const void * ptr, int type)



                      is a built-in construct that returns a constant number of bytes from ptr to the end of the object ptr pointer points to (if known at compile time). To determine the sizes of dynamically allocated objects the function relies on the allocation functions called to obtain the storage to be declared with the alloc_size attribute (see Common Function Attributes). __builtin_object_size never evaluates its arguments for side effects. If there are any side effects in them, it returns (size_t) -1 for type 0 or 1 and (size_t) 0 for type 2 or 3. If there are multiple objects ptr can point to and all of them are known at compile time, the returned number is the maximum of remaining byte counts in those objects if type & 2 is 0 and minimum if nonzero. If it is not possible to determine which objects ptr points to at compile time, __builtin_object_size should return (size_t) -1 for type 0 or 1 and (size_t) 0 for type 2 or 3.







                      share|improve this answer























                      • The differences between Intel64 and AMD64 are very minor and totally irrelevant to discussion of pointer widths. They're pretty much limited to a few kernel system-management differences; normal computation is identical across all x86-64; that's why we don't need separate binaries for Intel vs. AMD CPUs.

                        – Peter Cordes
                        May 20 at 1:33






                      • 1





                        You're assuming that CHAR_BIT is defined as 8. A 24-bit system is probably a DSP with 24-bit word-addressable memory, so a char is probably also 24-bit. Thus sizeof() everything = 1.

                        – Peter Cordes
                        May 20 at 1:35











                      • What did you say here or in the Q&As I linked to?

                        – Rob
                        May 20 at 1:44











                      • What did I say? I haven't commented on or answered that linked question, no idea what point you're making. Maybe you mean that a 24-bit system might not have 24-bit pointers; that's certainly possible, a C++ implementation is allowed to exist where some or all kinds of pointers are wider than its 24-bit char/int. But I meant for a "normal" 24-bit DSP, it probably wouldn't have byte-addressable memory with 3-byte "words", so a normal C++ implementation on it would probably have sizeof(void*) = sizeof(int*) = sizeof(char) = sizeof(int) = 1.

                        – Peter Cordes
                        May 20 at 2:06















                      0














                      Generally pointers will be size 2 on a 16-bit system, 3 on a 24-bit system, 4 on a 32-bit system, and 8 on a 64-bit system. It depends on the ABI and C implementation. AMD has long and legacy modes, and there are differences between AMD64 and Intel64 for Assembly language programmers but these are hidden for higher level languages.



                      Any problems with C/C++ code is likely to be due to poor programming practices and ignoring compiler warnings. See: "20 issues of porting C++ code to the 64-bit platform".



                      See also: "Can pointers be of different sizes?" and LRiO's answer:




                      ... you are asking about C++ and its compliant implementations, not some specific physical machine. I'd have to quote the entire standard in order to prove it, but the simple fact is that it makes no guarantees on the result of sizeof(T*) for any T, and (as a corollary) no guarantees that sizeof(T1*) == sizeof(T2*) for any T1 and T2).




                      Note: Where is answered by JeremyP, C99 section 6.3.2.3, subsection 8:




                      A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.




                      In GCC you can avoid incorrect assumptions by using built-in functions: "Object Size Checking Built-in Functions":




                      Built-in Function: size_t __builtin_object_size (const void * ptr, int type)



                      is a built-in construct that returns a constant number of bytes from ptr to the end of the object ptr pointer points to (if known at compile time). To determine the sizes of dynamically allocated objects the function relies on the allocation functions called to obtain the storage to be declared with the alloc_size attribute (see Common Function Attributes). __builtin_object_size never evaluates its arguments for side effects. If there are any side effects in them, it returns (size_t) -1 for type 0 or 1 and (size_t) 0 for type 2 or 3. If there are multiple objects ptr can point to and all of them are known at compile time, the returned number is the maximum of remaining byte counts in those objects if type & 2 is 0 and minimum if nonzero. If it is not possible to determine which objects ptr points to at compile time, __builtin_object_size should return (size_t) -1 for type 0 or 1 and (size_t) 0 for type 2 or 3.







                      share|improve this answer























                      • The differences between Intel64 and AMD64 are very minor and totally irrelevant to discussion of pointer widths. They're pretty much limited to a few kernel system-management differences; normal computation is identical across all x86-64; that's why we don't need separate binaries for Intel vs. AMD CPUs.

                        – Peter Cordes
                        May 20 at 1:33






                      • 1





                        You're assuming that CHAR_BIT is defined as 8. A 24-bit system is probably a DSP with 24-bit word-addressable memory, so a char is probably also 24-bit. Thus sizeof() everything = 1.

                        – Peter Cordes
                        May 20 at 1:35











                      • What did you say here or in the Q&As I linked to?

                        – Rob
                        May 20 at 1:44











                      • What did I say? I haven't commented on or answered that linked question, no idea what point you're making. Maybe you mean that a 24-bit system might not have 24-bit pointers; that's certainly possible, a C++ implementation is allowed to exist where some or all kinds of pointers are wider than its 24-bit char/int. But I meant for a "normal" 24-bit DSP, it probably wouldn't have byte-addressable memory with 3-byte "words", so a normal C++ implementation on it would probably have sizeof(void*) = sizeof(int*) = sizeof(char) = sizeof(int) = 1.

                        – Peter Cordes
                        May 20 at 2:06













                      0












                      0








                      0







                      Generally pointers will be size 2 on a 16-bit system, 3 on a 24-bit system, 4 on a 32-bit system, and 8 on a 64-bit system. It depends on the ABI and C implementation. AMD has long and legacy modes, and there are differences between AMD64 and Intel64 for Assembly language programmers but these are hidden for higher level languages.



                      Any problems with C/C++ code is likely to be due to poor programming practices and ignoring compiler warnings. See: "20 issues of porting C++ code to the 64-bit platform".



                      See also: "Can pointers be of different sizes?" and LRiO's answer:




                      ... you are asking about C++ and its compliant implementations, not some specific physical machine. I'd have to quote the entire standard in order to prove it, but the simple fact is that it makes no guarantees on the result of sizeof(T*) for any T, and (as a corollary) no guarantees that sizeof(T1*) == sizeof(T2*) for any T1 and T2).




                      Note: Where is answered by JeremyP, C99 section 6.3.2.3, subsection 8:




                      A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.




                      In GCC you can avoid incorrect assumptions by using built-in functions: "Object Size Checking Built-in Functions":




                      Built-in Function: size_t __builtin_object_size (const void * ptr, int type)



                      is a built-in construct that returns a constant number of bytes from ptr to the end of the object ptr pointer points to (if known at compile time). To determine the sizes of dynamically allocated objects the function relies on the allocation functions called to obtain the storage to be declared with the alloc_size attribute (see Common Function Attributes). __builtin_object_size never evaluates its arguments for side effects. If there are any side effects in them, it returns (size_t) -1 for type 0 or 1 and (size_t) 0 for type 2 or 3. If there are multiple objects ptr can point to and all of them are known at compile time, the returned number is the maximum of remaining byte counts in those objects if type & 2 is 0 and minimum if nonzero. If it is not possible to determine which objects ptr points to at compile time, __builtin_object_size should return (size_t) -1 for type 0 or 1 and (size_t) 0 for type 2 or 3.







                      share|improve this answer













                      Generally pointers will be size 2 on a 16-bit system, 3 on a 24-bit system, 4 on a 32-bit system, and 8 on a 64-bit system. It depends on the ABI and C implementation. AMD has long and legacy modes, and there are differences between AMD64 and Intel64 for Assembly language programmers but these are hidden for higher level languages.



                      Any problems with C/C++ code is likely to be due to poor programming practices and ignoring compiler warnings. See: "20 issues of porting C++ code to the 64-bit platform".



                      See also: "Can pointers be of different sizes?" and LRiO's answer:




                      ... you are asking about C++ and its compliant implementations, not some specific physical machine. I'd have to quote the entire standard in order to prove it, but the simple fact is that it makes no guarantees on the result of sizeof(T*) for any T, and (as a corollary) no guarantees that sizeof(T1*) == sizeof(T2*) for any T1 and T2).




                      Note: Where is answered by JeremyP, C99 section 6.3.2.3, subsection 8:




                      A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.




                      In GCC you can avoid incorrect assumptions by using built-in functions: "Object Size Checking Built-in Functions":




                      Built-in Function: size_t __builtin_object_size (const void * ptr, int type)



                      is a built-in construct that returns a constant number of bytes from ptr to the end of the object ptr pointer points to (if known at compile time). To determine the sizes of dynamically allocated objects the function relies on the allocation functions called to obtain the storage to be declared with the alloc_size attribute (see Common Function Attributes). __builtin_object_size never evaluates its arguments for side effects. If there are any side effects in them, it returns (size_t) -1 for type 0 or 1 and (size_t) 0 for type 2 or 3. If there are multiple objects ptr can point to and all of them are known at compile time, the returned number is the maximum of remaining byte counts in those objects if type & 2 is 0 and minimum if nonzero. If it is not possible to determine which objects ptr points to at compile time, __builtin_object_size should return (size_t) -1 for type 0 or 1 and (size_t) 0 for type 2 or 3.








                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered May 20 at 1:20









                      RobRob

                      1,11011418




                      1,11011418












                      • The differences between Intel64 and AMD64 are very minor and totally irrelevant to discussion of pointer widths. They're pretty much limited to a few kernel system-management differences; normal computation is identical across all x86-64; that's why we don't need separate binaries for Intel vs. AMD CPUs.

                        – Peter Cordes
                        May 20 at 1:33






                      • 1





                        You're assuming that CHAR_BIT is defined as 8. A 24-bit system is probably a DSP with 24-bit word-addressable memory, so a char is probably also 24-bit. Thus sizeof() everything = 1.

                        – Peter Cordes
                        May 20 at 1:35











                      • What did you say here or in the Q&As I linked to?

                        – Rob
                        May 20 at 1:44











                      • What did I say? I haven't commented on or answered that linked question, no idea what point you're making. Maybe you mean that a 24-bit system might not have 24-bit pointers; that's certainly possible, a C++ implementation is allowed to exist where some or all kinds of pointers are wider than its 24-bit char/int. But I meant for a "normal" 24-bit DSP, it probably wouldn't have byte-addressable memory with 3-byte "words", so a normal C++ implementation on it would probably have sizeof(void*) = sizeof(int*) = sizeof(char) = sizeof(int) = 1.

                        – Peter Cordes
                        May 20 at 2:06

















                      • The differences between Intel64 and AMD64 are very minor and totally irrelevant to discussion of pointer widths. They're pretty much limited to a few kernel system-management differences; normal computation is identical across all x86-64; that's why we don't need separate binaries for Intel vs. AMD CPUs.

                        – Peter Cordes
                        May 20 at 1:33






                      • 1





                        You're assuming that CHAR_BIT is defined as 8. A 24-bit system is probably a DSP with 24-bit word-addressable memory, so a char is probably also 24-bit. Thus sizeof() everything = 1.

                        – Peter Cordes
                        May 20 at 1:35











                      • What did you say here or in the Q&As I linked to?

                        – Rob
                        May 20 at 1:44











                      • What did I say? I haven't commented on or answered that linked question, no idea what point you're making. Maybe you mean that a 24-bit system might not have 24-bit pointers; that's certainly possible, a C++ implementation is allowed to exist where some or all kinds of pointers are wider than its 24-bit char/int. But I meant for a "normal" 24-bit DSP, it probably wouldn't have byte-addressable memory with 3-byte "words", so a normal C++ implementation on it would probably have sizeof(void*) = sizeof(int*) = sizeof(char) = sizeof(int) = 1.

                        – Peter Cordes
                        May 20 at 2:06
















                      The differences between Intel64 and AMD64 are very minor and totally irrelevant to discussion of pointer widths. They're pretty much limited to a few kernel system-management differences; normal computation is identical across all x86-64; that's why we don't need separate binaries for Intel vs. AMD CPUs.

                      – Peter Cordes
                      May 20 at 1:33





                      The differences between Intel64 and AMD64 are very minor and totally irrelevant to discussion of pointer widths. They're pretty much limited to a few kernel system-management differences; normal computation is identical across all x86-64; that's why we don't need separate binaries for Intel vs. AMD CPUs.

                      – Peter Cordes
                      May 20 at 1:33




                      1




                      1





                      You're assuming that CHAR_BIT is defined as 8. A 24-bit system is probably a DSP with 24-bit word-addressable memory, so a char is probably also 24-bit. Thus sizeof() everything = 1.

                      – Peter Cordes
                      May 20 at 1:35





                      You're assuming that CHAR_BIT is defined as 8. A 24-bit system is probably a DSP with 24-bit word-addressable memory, so a char is probably also 24-bit. Thus sizeof() everything = 1.

                      – Peter Cordes
                      May 20 at 1:35













                      What did you say here or in the Q&As I linked to?

                      – Rob
                      May 20 at 1:44





                      What did you say here or in the Q&As I linked to?

                      – Rob
                      May 20 at 1:44













                      What did I say? I haven't commented on or answered that linked question, no idea what point you're making. Maybe you mean that a 24-bit system might not have 24-bit pointers; that's certainly possible, a C++ implementation is allowed to exist where some or all kinds of pointers are wider than its 24-bit char/int. But I meant for a "normal" 24-bit DSP, it probably wouldn't have byte-addressable memory with 3-byte "words", so a normal C++ implementation on it would probably have sizeof(void*) = sizeof(int*) = sizeof(char) = sizeof(int) = 1.

                      – Peter Cordes
                      May 20 at 2:06





                      What did I say? I haven't commented on or answered that linked question, no idea what point you're making. Maybe you mean that a 24-bit system might not have 24-bit pointers; that's certainly possible, a C++ implementation is allowed to exist where some or all kinds of pointers are wider than its 24-bit char/int. But I meant for a "normal" 24-bit DSP, it probably wouldn't have byte-addressable memory with 3-byte "words", so a normal C++ implementation on it would probably have sizeof(void*) = sizeof(int*) = sizeof(char) = sizeof(int) = 1.

                      – Peter Cordes
                      May 20 at 2:06

















                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56208872%2fsize-of-pointers-and-architecture%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      How to write a 12-bar blues melodyI-IV-V blues progressionHow to play the bridges in a standard blues progressionHow does Gdim7 fit in C# minor?question on a certain chord progressionMusicology of Melody12 bar blues, spread rhythm: alternative to 6th chord to avoid finger stretchChord progressions/ Root key/ MelodiesHow to put chords (POP-EDM) under a given lead vocal melody (starting from a good knowledge in music theory)Are there “rules” for improvising with the minor pentatonic scale over 12-bar shuffle?Confusion about blues scale and chords

                      What if the end-user didn't have the required library?What is setup.py?What is a clean, pythonic way to have multiple constructors in Python?What does Ruby have that Python doesn't, and vice versa?What is the reason for having '//' in Python?How do I create a namespace package in Python?How to package shared objects that python modules depend on?setuptools vs. distutils: why is distutils still a thing?Navigation in Windows 10 vs code not going to virtualenv library when the same library is installed at user levelPython create package for local usePackaging a project that uses multiple python versionsWhy is permission denied on pip install except for when “--user” is included at end of command?

                      Esgonzo ibérico Índice Descrición Distribución Hábitat Ameazas Notas Véxase tamén "Acerca dos nomes dos anfibios e réptiles galegos""Chalcides bedriagai"Chalcides bedriagai en Carrascal, L. M. Salvador, A. (Eds). Enciclopedia virtual de los vertebrados españoles. Museo Nacional de Ciencias Naturales, Madrid. España.Fotos