0

If uint8_t exist, is a pointer to uint8_t equivalent to a pointer to unsigned char? Means it can be used to access any object and does not cause UB when accessing a different object. I know that this rules:

int intVar=0;
unsigned char *charPtr=&intVar; //completely valid and does not cause UB
printf("%X ",*charPtr); //this is also valid and does not cause UB

struct SomeStruct_T structVar={};
int *intPtr=&structVar; //This causes UB

But what about this:

int intVar=0;
uint8_t *uint8Ptr=&intVar; //Is this valid?
printf("%X ",*uint8Ptr);   //If yes, is this also valid?

GCC with -Wincompatible-pointer-types warns about unsigned char *charPtr=&intVar; and uint8_t *uint8Ptr=&intVar;, but with a cast this warning goes away. This does not answer the question. There is probably no system where uint8_t * will be different from unsigned char * but what does the standard say?

This question is about the pointer type which points to unsigned char or uint8_t, not about the data type unsigned char or uint8_t itself. There are some fundamental properties of unsigned char * that may or may not apply to uint8_t *, such as being able to access any object, that are not relevant for the type unsigned char itself. This question is therefore not a duplicate of the linked question. The linked question is also about C++, but i don't ask about C++, my question is about C. Please do not mark this question as duplicate of the linked question, because the question is definitely not the same.

  • 1
    seems a dupe of [When is uint8\_t ≠ unsigned char?](https://stackoverflow.com/questions/16138237/when-is-uint8-t-%e2%89%a0-unsigned-char) – underscore_d Jan 21 '21 at 16:36
  • I think `int *intPtr=&structVar; //This causes UB` is fine as long (not UB) as you don't dereference it (I would need to dig up the standard to know for certain). – Maciej Piechotka Jan 21 '21 at 16:36
  • @underscore_d The linked question is about the data type, not the pointer type. – 12431234123412341234123 Jan 21 '21 at 16:43
  • @underscore_d Please read both questions before you mark a duplicate, thank you. The other question is about `uint8_t` vs `unsigned char` not `uint8_t *` vs `unsigned char *` and the linked question is about C++ this question is about C. – 12431234123412341234123 Jan 21 '21 at 16:50
  • I can read fine, thank you. C++ just inherits these types from C, and the behaviour/validity of the pointers is based on the types they point to, so it seems a clear dupe to me. Clearly the other user who voted to close as a duplicate also agreed, so I can't be the only one. – underscore_d Jan 21 '21 at 17:13
  • @underscore_d But you didn't. There are a lot of questions that are falsely marked as duplucate, so don't make an appeal to popularity fallacy. There are special characteristics of `unsigned char *` that are not directly related to `unsinged char` such as that you can access any object with `unsigned char *`. Marking it as duplicate of the linked question just shows you didn't understand or read the question or you don't know C well enough. – 12431234123412341234123 Jan 21 '21 at 17:23
  • What? It's `unsigned char*` (and `char*`, and `std::byte*`) that has the special properties. Therefore, `uint8_t*` will only have said props iff `uint8_t` is a typedef to `unsigned char`. – underscore_d Jan 21 '21 at 17:32
  • @underscore_d This question is about C, not C++, `std::byte*` is not valid C code. The linked question does not say `uint8_t` has to be a typedef of `unsigned char` in C (there are comments say it could be in C++, but then again, this question is about C). If it has to be it would answer the question. – 12431234123412341234123 Jan 21 '21 at 17:36

1 Answers1

2

Proof:

The standard asserts that sizeof(unsigned char) is 1.

The standard asserts there are no fractional sizes.

The standard does not allow uint8_t to have padding bits.

The standard does not allow unsigned char to have padding bits.

Therefore:

You can't have two unsigned chars in an uint_8 by pigeonhole principle.

The size of uint_8 must be 1.

Therefore blitting unsigned char through uint8_t or uint8_t through unsigned char is defined.

However, your code isn't completely valid because you took an endian dependency when you casted the pointer to int to a pointer to unsigned char. In C, pointer casts are transitive except when casting to or from a function pointer to a non-function-pointer so we may analyze as though you cast directly from int * to unsigned char *.*

*This is only true of casts. Blitting through a union or memcpy can defy this.

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • Not necessarily. It could be that a system has a native data with of 16 bit and 128 KiB RAM. The `char *` and `void *` pointer would need 2 words (2*16 bit) on such a system. Maybe the compiler puts all possible `uint8_t` variables, including stack and heap, in the lower 64 KiB so a `uint8_t *` pointer only needs 1 word and not 2 and making `uint8_t *` not able to accessing everything. – 12431234123412341234123 Jan 21 '21 at 16:46
  • @12431234123412341234123: You forgot about `malloc()`. The runtime can't possibly make this optimization because it doesn't know that `malloc()` is allocating uint8_t or not. – Joshua Jan 21 '21 at 16:49
  • I said _including stack and heap_. And please keep in mind that there are systems without `malloc()`. A freestanding environment does not need to provide `malloc()` – 12431234123412341234123 Jan 21 '21 at 16:51
  • 2
    @12431234123412341234123 What about 6.3.2.3/7: "A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned 68) for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer."? Surely `unsigned char` and `uint8_t` have the same alignment, so the pointer values convertible both ways? – Ian Abbott Jan 21 '21 at 16:58
  • @12431234123412341234123 if `CHAR_BITS > 8` then no `uint8_t` – 0___________ Jan 21 '21 at 17:06
  • @0___________ Yes? We all know that, but how is that relevant? – 12431234123412341234123 Jan 21 '21 at 17:19