When is uintptr_t preferred over intptr_t?

前端 未结 4 2086
甜味超标
甜味超标 2021-02-05 09:30

Given the requirement that I need to store the value of a \"generic\" pointer in a struct and have no interest in the pointed-at memory itself, I find it more semantically corre

4条回答
  •  青春惊慌失措
    2021-02-05 10:10

    You should pick the type appropriate for the given system and program. Most of the time, pointers are positive address values, in which case uintptr_t is the correct type. But some systems use negative addresses as a way to express kernel space, as explained here: Can a pointer (address) ever be negative? This would be the reason why there are two different types.


    As for (u)intptr_t vs void* for a generic pointer type, the former is preferred in rugged, professional programs. There are many problems/bug sources associated with pointer types:

    • All manner of different pointer types are most often not compatible with each other and cannot alias. This is a problem with object pointers as well as function pointers.
    • You often have type qualifiers like const, which makes pointer conversions to/from that type questionable or poorly-defined.
    • Conversions to/from void* and other pointer types happen implicitly, making it easy for bugs related to using the wrong pointer type to slip through unnoticed. This was fixed in C++, but remains a hazard in C. Take for example the old but classic "I forgot to include stdlib.h while using malloc in C90" bug.
    • Performing arithmetic on a pointer comes with numerous pitfalls, because you can only safely do arithmetic on a pointer which points at an allocated array. However, one can often have a memory address for a lot of other reasons than pointing at an array, as anyone working with embedded systems knows.
    • You can't even perform pointer arithmetic calculations on a void*. Doing so relies on non-standard compiler extensions.

    That being said, a whole lot of legacy code relies on void pointers, and it's perfectly fine to use them in a restricted context. Some examples would be canonical code relying on generic callback functions: bsearch, qsort, pthreads and similar.

    I would however not recommend to use void pointers when designing new C programs - they are, in my opinion, best regarded as a dangerous feature of the past. There exist better and safer methods of generic C programming nowadays, such as C11 _Generic, tricks using designated initializers, passing parameters as array pointers (to VLA), bounds-checking at compile time with static_assert etc. Some examples can be found in my answer here: How to create type safe enums?.

提交回复
热议问题