0

I have tried to wrap my head around this for some time now, and have searched for related questions. I have found some answers that make some sense, but apparently I need this carved in stone.

Currently I'm in the process of learning some firmware for a product. A set of pointers have been initialized as uint8_t, like the following example:

uint8_t *pwhatevs; 

The sizeof the above would return 1 (one byte). When this pointer is assigned later in the firmware, it is pointing to a 32-bit address in the following way:

pwhatevs = (uint8_t *)&whatever; 

This syntax appears odd to me. The initial part (uint8_t *) is an 8-bit pointer typecast. But if I take the sizeof pwhatevs now it returns 4 (4 bytes), which I'm both not surprised of but then again very surprised due to the pointer typecast. Can someone explain this? If additional information is needed I will provide as much as I can!

Edit: In another question relating to pointer size it was mentioned that the size of a pointer is system dependent like 16, 32 or 64 bits. This does make sense, but then why is the *pwhatevs when initialized not 4 bytes in size?

Edit 2: I can't share the entire code since it is an actual product, but will do it the following way. If this isn't sufficient, I will have to work on a specific example.

code

Variables with assigned size from code

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • It depends on the addressing of the platform you are running, 32 bits is the addressbus size, in other words the pointer size will always be 4byte – Kraego Aug 30 '23 at 07:27
  • 3
    `The sizeof the above would return 1 (one byte)` Please show your code. `Can someone explain this?` I challenge the method of measurement into question. I suspect you made an error in your code. I doubt a pointer size has a sizeof of 1. `why is the *pwhatevs` The sizeof of *pwhatevs is 1, the sizeof of pwhatevs could be 4. Please be exact, please show the code. – KamilCuk Aug 30 '23 at 07:28
  • "_pointers have been initialized as uint8_t_" Pointers are pointers that are the size of pointers (that hold addresses). The example given has been initialised as "**uint8_t *;**" It is a "pointer to things that are unsigned _single_ bytes." – Fe2O3 Aug 30 '23 at 07:31
  • Kraego, please see my edit note :) My thought is that when the pointer is made to point to an actual address then the (uint_8 *) typecast is "forced" to (uint32_t) due to the addressbus size. Would that make sense? – TheLostProgrammer Aug 30 '23 at 07:34
  • It s like Fe203 said you can see the pointer type as hint to what the pointer is pointing, the address would always have the same size regardless to what it points – Kraego Aug 30 '23 at 07:38
  • `double *pDbl;` declares a pointer (4 bytes on your system?) that will be used to point to an 8 byte _object_ (a `double`)... For a purpose (such as serialising those bytes for transmission), you might write something like `uint8_t *p8 = (uint8_t *) pDbl;`. You can then deal with those 8 bytes individually... Does this help? – Fe2O3 Aug 30 '23 at 07:40
  • Addresses come in 1-size for a given processor. Your addresses are 4-bytes according to your question -- so pointers (which are just normal variables that hold the address of something else) must be capable of holding 4-bytes. Your declaration `uint8_t *foo` just means `foo` is a pointer to a `uint8_t`, the `uint8_t` has nothing to do with the `sizeof (a_pointer);` it's just the type being *pointed to...* – David C. Rankin Aug 30 '23 at 08:03
  • 2
    Confusing `sizeof(pwhatevs)` and `sizeof(*pwhatevs)` , i.e. sizeof pointer vs sizeof element pointed by. – Jean-Baptiste Yunès Aug 30 '23 at 08:07

2 Answers2

6

You are confusing the size of the pointer with the size of the thing the pointer points to.

For a most platforms you encounter today (x86, ARM, etc), all pointers will always be the same size1, regardless of the type they point to. For a platform with a 32 bit address space, pointers will likely be 4 bytes (32 bits) long. There is no such thing as an "8-bit pointer typecast": the (uint8_t*) type is "a pointer to an 8-bit variable", not an "8-bit pointer".

For your example:

(sizeof pwhatevs) == 4 <-- The size of the pointer type itself: (sizeof (uint8_t*)). This might also be 2 or 8, depending on the platform.

(sizeof *pwhatevs) == 1 <-- The size of the type the pointer points to (sizeof (uint8_t))

Most importantly, the sizeof of anything in C can never change2. Once a variable is declared it has a fixed sizeof. It is not possible that assigning something to a pointer changes its size. You are doing something wrong when measuring its size, but without your complete code it is impossible to tell what.


1 For more in-depth information, see for example Can pointers be of different sizes?

2 Of course the size of a variable can be different if you compile the same code for a different platform, or on a different operating system, or with different compiler flags. But it can never change during a single compilation process of a single .c file. Not by assignments, nor by anything else.

Fritz
  • 1,293
  • 15
  • 27
  • 1
    Re “For a given platform, *all pointers will **always** be the same size*, regardless of the type they point to”: This is not true. Most modern C implementations use one size for all pointer types, but the C standard does not require it, and there are C implementations that have pointers of different sizes. (The standard does require certain categories of some types of pointers to be the same size.) – Eric Postpischil Aug 30 '23 at 07:59
  • 2
    Good point, although I think that this (today mostly irrelevant) fact would be too confusing for a beginner who is struggling with the basic concept of pointer types. I will adjust the text. – Fritz Aug 30 '23 at 08:11
  • I'm well aware it would be ideal with the complete code, but unfortunately I can't post that. The answer you have provided is also my understanding of it. But would the (uint8_t *) not be redundant in this context? pwhatevs = (uint8_t *) &whatever; – TheLostProgrammer Aug 30 '23 at 08:39
  • 1
    @TheLostProgrammer If you cannot post the whole code, then you should post a minimal, reproducible example: https://stackoverflow.com/help/minimal-reproducible-example. Chances are, you will figure it out yourself while you do that (happens to all of us). If `whatever` is a `uint8_t`, then that type cast is indeed redundant. And it is bad practice as it would hide an error message if someone later changed the type of `whatever` but forgot to change the type of `pwhatevs`. But type casting has nothing to do with the sizes of the types/pointers in question. As I said, pointer sizes don't change. – Fritz Aug 30 '23 at 09:30
-1
  • uint8_t *pwhatevs; The sizeof the above would return 1 (one byte).

    No it wouldn't, have you tried? sizeof(pwhatevs) will equal the size of the address bus, which on all mainstream computers will be either 2, 4 or 8 bytes. sizeof(*pwatevs) will however return 1 since that's the size of the pointed-at type. The problem here seems to be that you confuse the type pointed at with the pointer variable itself.

  • This syntax appears odd to me. The initial part (uint8_t *) is an 8 bit pointer typecast.

    Again, there is no such thing as "an 8 bit pointer typecast". This is rather a cast to a pointer pointing at an 8-bit type. The size of the pointer and the size of the pointed-at type are different things.

  • But if I take the sizeof pwhatevs now it returns 4

    It did that all along, regardless of what the pointer pointed at. You cannot change the size of pointers in C, they have a fixed size determined by the compiler, based on what's suitable for the given CPU.

Lundin
  • 195,001
  • 40
  • 254
  • 396