1

This question is based on the following C example, which I made for this post:

#include <stdio.h>
#include <stdint.h>

typedef struct 
{
    uint32_t temp;
    uint32_t temp2;
} Foo_t;

static void doFoo(const Foo_t *fooAPtr, const Foo_t **fooBPtr);

static void doFoo(const Foo_t *fooAPtr, const Foo_t **fooBPtr)
{
    /* Assinging B to A just as an example */
    *fooBPtr = fooAPtr;
}

int main()
{
    Foo_t fooA = {1, 2};
    Foo_t *fooAPtr = &fooA;
    const Foo_t *fooBPtr = 0;

    doFoo(fooAPtr, &fooBPtr);

    printf("\n FooAPtr == %p, FooBPtr == %p \n", fooAPtr, fooBPtr);

    printf("\n FooAPtr == %i %i |_| FooBPtr == %i %i \n", fooAPtr->temp, fooAPtr->temp2, fooBPtr->temp, fooBPtr->temp2);

    return 0;
}

This code can be run at the link below:

https://onlinegdb.com/rJdHGFNYB

I am questioning my pointer logic and wanted to verify my assumptions about the code. This is my interpretation of the doFoo() function above:

fooAPtr == A constant pointer, pointing to the memory location of a structure of type Foo_t. The const denotes that the address of that memory location should not be changed

fooBPtr == A mutable pointer, pointing to an address that points to the memory location of a Foo_t structure. The const denotes that the address being pointed to cannot change?

It’s pathetic that I am asking this, but I can’t wrap my head around the particular use case. The code works as expected, but that doesn’t mean it’s correct.

So, the question is, is my interpretation of the pointer logic above correct? Specifically, my use of const, and the layers of indirection for fooBPtr. For context, the goal of doFoo() is to assign fooBPtr to fooAPtr via function parameters, not by returning anything.

Birts
  • 149
  • 1
  • 8
  • https://cdecl.org/ is your friend. – hyde Oct 16 '19 at 12:01
  • Possible duplicate of [What is the difference between const int\*, const int \* const, and int const \*?](https://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const) – gstukelj Oct 16 '19 at 12:02
  • @hyde No, it is rather unfriendly. "Syntax error". – Lundin Oct 16 '19 at 12:02
  • You are supposed to read it right to left, i.e. `const Foo_t *` or `Foo_t const *` is a "pointer to const". And `const Foo_t **` is a "pointer to a pointer to const". It wouldn't make sense to use `Foo_t * const`, because nobody really cares if your function changes the value of `fooAPtr` internally. – vgru Oct 16 '19 at 12:15
  • @Lundin It's that evil `typedef`. For example `const struct Foo **fooBPtr;` works nicely. – hyde Oct 16 '19 at 12:22
  • @Lundin It seems to understand `static void doFoo(const struct Foo *, const struct Foo **);` so yeah some limitations. – hyde Oct 16 '19 at 19:07

3 Answers3

1

The term "constant pointer" isn't helpful since it has multiple interpretations.

  • fooAPtr is a pointer to read-only data. The pointer itself can be changed.
  • fooBPtr is a pointer to pointer to read-only data. The pointer-to-pointer itself can be changed. The pointed-at pointer can be changed.

Please note that const in this case sticks with the pointed-at data. It may be helpful to read the declarations from right to left.

More info: What is the difference between const int*, const int * const, and int const *?

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

const Foo_t *fooAPtr says fooAPtr points to a const Foo_t. So does Foo_t const * fooAPtr.

Foo_t * const fooAPtr says fooAPtr is const and points to Foo_t.

const Foo_t **fooBPtr says fooBPtr points to a pointer to a const Foo_t.

foo_t const **fooBPtr also says fooBPtr points to a pointer to a const Foo_t.

foo_t * const *fooBPtr says fooBPtr points to a const pointer to a Foo_t.

Foo_t ** const fooBPtr says fooBPtr is const and points to a pointer to a Foo_t.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

Actually, in both pointer declarations the const refers to the fact that the memory region occupied by the object of type Foo_t isn't allowed to change.

  • const Foo_t *fooAPtr: pointer to const Foo_t;
  • const Foo_t **fooBPtr: pointer to pointer to const Foo_t.

If you'd like to turn into const the pointer to which fooBPtr points to, you'd have to change its declaration to:

const Foo_t * const * fooBPtr;
Tarc
  • 3,214
  • 3
  • 29
  • 41