sizeof (int) == sizeof (void*)?

后端 未结 10 880
有刺的猬
有刺的猬 2020-12-03 01:50

Is there an integer type with the same size as pointer? Guaranteed on all microarchitectures?

相关标签:
10条回答
  • 2020-12-03 02:26

    The C99 standard defines standard int types:

    7.18.1.4 Integer types capable of holding object pointers The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

        intptr_t
    

    The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

       uintptr_t
    

    These types are optional.

    C99 also defines size_t and ptrdiff_t:

    The types are

      ptrdiff_t
    

    which is the signed integer type of the result of subtracting two pointers;

      size_t
    

    which is the unsigned integer type of the result of the sizeof operator; and

    The architectures I've seen have the maximum size of an object equal to the whole memory, so sizeof(size_t) == sizeof(void*), but I'm not aware of anything that is both portable to C89 ( which size_t is ) and guaranteed to be large enough ( which uintptr_t is ).

    0 讨论(0)
  • 2020-12-03 02:27

    int data type would be the answer on most architectures.

    But thre is NO guarantee to this for ANY (micro)architecture.

    0 讨论(0)
  • 2020-12-03 02:30

    Simply put, no. Not guaranteed on all architectures.

    My question is: why? If you want to allocate a type big enough to store a void*, the best thing to allocate is (surprisingly enough :-) a void*. Why is there a need to fit it within an int?

    EDIT: Based on your comments to your duplicate question, you want to store special values of the pointer (1,2,3) to indicate extra information.

    NO!! Don't do this!!. There is no guarantee that 1, 2 and 3 aren't perfectly valid pointers. That may be the case in systems where you're required to align pointers on 4-byte boundaries but, since you asked about all architectures, I'm assuming you have portability as a high value.

    Find another way to do it that's correct. For example, use the union (syntax from memory, may be wrong):

    typedef struct {
        int isPointer;
        union {
            int intVal;
            void *ptrVal;
        }
    } myType;
    

    Then you can use the isPointer 'boolean' to decide if you should treat the union as an integer or pointer.

    EDIT:

    If execution speed is of prime importance, then the typedef solution is the way to go. Basically, you'll have to define the integer you want for each platform you want to run on. You can do this with conditional compilation. I would also add in a runtime check to ensure you've compiled for each platform correctly thus (I'm defining it in the source but you would pass that as a compiler flag, like "cc -DPTRINT_INT"):

    #include <stdio.h>
    #define PTRINT_SHORT
    #ifdef PTRINT_SHORT
        typedef short ptrint;
    #endif
    #ifdef PTRINT_INT
        typedef int ptrint;
    #endif
    #ifdef PTRINT_LONG
        typedef long ptrint;
    #endif
    #ifdef PTRINT_LONGLONG
        typedef long long ptrint;
    #endif
    
    int main(void) {
        if (sizeof(ptrint) != sizeof(void*)) {
            printf ("ERROR: ptrint doesn't match void* for this platform.\n");
            printf ("   sizeof(void*    ) = %d\n", sizeof(void*));
            printf ("   sizeof(ptrint   ) = %d\n", sizeof(ptrint));
            printf ("   =================\n");
            printf ("   sizeof(void*    ) = %d\n", sizeof(void*));
            printf ("   sizeof(short    ) = %d\n", sizeof(short));
            printf ("   sizeof(int      ) = %d\n", sizeof(int));
            printf ("   sizeof(long     ) = %d\n", sizeof(long));
            printf ("   sizeof(long long) = %d\n", sizeof(long long));
            return 1;
        }
    
        /* rest of your code here */
    
        return 0;
    }
    

    On my system (Ubuntu 8.04, 32-bit), I get:

    ERROR: ptrint typedef doesn't match void* for this platform.
       sizeof(void*    ) = 4
       sizeof(ptrint   ) = 2
       =================
       sizeof(short    ) = 2
       sizeof(int      ) = 4
       sizeof(long     ) = 4
       sizeof(long long) = 8
    

    In that case, I'd know I needed to compile with PTRINT_INT (or long). There may be a way of catching this at compile time with #if, but I couldn't be bothered researching it at the moment. If you strike a platform where there's no integer type sufficient for holding a pointer, you're out of luck.

    Keep in mind that using special pointer values (1,2,3) to represent integers may also not work on all platforms - this may actually be valid memory addresses for pointers.

    Still ,if you're going to ignore my advice, there's not much I can do to stop you. It's your code after all :-). One possibility is to check all your return values from malloc and, if you get 1, 2 or 3, just malloc again (i.e., have a mymalloc() which does this automatically). This'll be a minor memory leak but it'll guarantee no clashes between your special pointers and real pointers.

    0 讨论(0)
  • 2020-12-03 02:36

    No.

    I do not believe the C standard even specifies standard int sizes. Combine that with all the architectures out there (8/16/32/64bit etc) and there is no way to guarantee anything.

    0 讨论(0)
  • 2020-12-03 02:38

    No, the closest you will come to a portable pointer-capable integer type would be intptr_t and ptrdiff_t.

    0 讨论(0)
  • 2020-12-03 02:39

    The standard solution to this problem is to write a small program which checks the sizes of all int types (short int, int, long int) and compares them to void*. If there is a match, it emits a piece of code which defines the intptr type. You can put this in a header file and use the new type.

    It's simple to include this code in the build process (using make, for example)

    0 讨论(0)
提交回复
热议问题