1

I need to initialize an array of pointers to pointers to four variables a, b, c and d in this way:

float a = 2.8f, b = 3.7f, c = 4.6f, d = 5.5f;
float *pts[] = { &a, &b, &c, &d };
float **ptpts[4];

void main() {
    ptpts[0] = &pts[0];
    ptpts[1] = &pts[1];
    ptpts[2] = &pts[2];
    ptpts[3] = &pts[3];

    int i;
    for (i = 0; i < 4; i++) {
        printf("ptpts[%d] = %f\n", i, **ptpts[i]);
    }
}

Isn't there a simpler way to initialize the array ptpts directly at declaration using directly the array pts in order to get rid of the assignment of each element in ptpts one by one. Something like that (but doesn't work):

float *pts[] = { &a, &b, &c, &d };
float **ptpts = &pts; // => initialization from incompatible pointer type

In other words, isn't there a way to get the corresponding array of references from an array of pointers ?

Edit:

Following some comments, I give here a piece of background to explain how I came to that question. This may help to propose the solution or give idea for a better architecture.

I have the following interface (interface.h) for the program I'm developing. Depending on a flag PTTYPE defined at compilation time, the interface will be a set of variables or a set of pointers depending on the environment where the program is deployed. The program must be compliant with both kind of interface type (PTTYPE=1 or PTTYPE=0).

// interface.h 
#if PTTYPE
    float *pta, *ptb, *ptc, *ptd;
    #define a (*pta)
    #define b (*ptb)
    #define c (*ptc)
    #define d (*ptd)
#else
    float a, b, c, d;
#endif

I'm not the owner of this interface file and can't modify it. I must just include this file in my program and want to have a simple and unique way to reach the values. That's why I thought about using an array of pointers to pointers and would have something like that:

#include "interface.h"

#if PTTYPE
    float **ptpts[]={ &pta, &ptb, &ptc, &ptd };
#else
    float *pts[]={ &a, &b, &c, &d };
    float **ptpts = &pts; // => initialization from incompatible pointer
#end

void main() {
    a=2.8f;
    b=3.7f;
    c=4.6f;
    d=5.5f;

    int i;
    for (i = 0; i < 4; i++) {
        printf("ptpts[%d] = %f\n", i, **ptpts[i]);
    }
}
5
  • Try float **ptpts[] = { &pts[0], &pts[1], &pts[2], &pts[3] }; and let the compiler provide the dimension. Commented Aug 16, 2022 at 8:02
  • Is there a reason why you can't drop all this slow and cumbersome pointer syntax in favour of a union? Example: godbolt.org/z/vb6ahhr7z Commented Aug 16, 2022 at 8:06
  • @Lundin The example suggested omits a layer of pointers... For whatever reason, this indirection may be essential. Commented Aug 16, 2022 at 8:14
  • @Fe2O3 I really don't see why, hence the question "is there a reason". Because all the pointers achieve is extra de-referencing and cache misses. Commented Aug 16, 2022 at 9:08
  • I edited the question to add some background and explain the reason of the question. Commented Aug 16, 2022 at 9:47

4 Answers 4

3
float ..... = &pts;

Yes you can but you need another pointer type (pointer to array):

float a = 2.8f, b = 3.7f, c = 4.6f, d = 5.5f;
float *pts[] = { &a, &b, &c, &d };
float *(*ptpts)[4] = &pts;

for (size_t i = 0; i < 4; i++) 
{
    printf("*ptpts[0][%zu] = %f\n", i, *ptpts[0][i]);
}

or

    for (size_t i = 0; i < 4; i++) {
        printf("ptpts[%zu] = %f\n", i, *(*ptpts[i]));
    }

Yes you can even without any variables

int main(void)
{
    float **pptrs[] = {(float **){&(float *){&(float){1.0f}}}, 
                    (float **){&(float *){&(float){2.0f}}}, 
                    (float **){&(float *){&(float){3.0f}}}, 
                    (float **){&(float *){&(float){4.0f}}}, };
}
Sign up to request clarification or add additional context in comments.

5 Comments

The 'no variable' example is interesting. Are the float values mutable (read/write)?
Yes but they are local. Read about compound literals
The first proposal is close to what I'm looking for but not exactly. I access now the values of ptpts with *ptpts[0][i] and not anymore with **ptpts[i] which is incompatible with my need (see my edit). The third proposal is interesting. Maybe a mix between the first and the third ?
@steens you can of couse
@0___________ thanks, with the compound literals I was able to solve my problem (see answer below).
1

The array can be defined and initialized inline this way:

float **ptpts[] = { &pts[0], &pts[1], &pts[2], &pts[3]};

If the array is global and the initization local in main, a loop or a series of assignments is required.

Comments

0

It's okay to use whitespace to aid readability.

int main() {
    float a=2.8f, b=3.7f, c=4.6f, d=5.5f;
    float *pts[]={ &a, &b, &c, &d };

    // What you want?
    float **ptpts[] = { &pts[0],  &pts[1], &pts[2],  &pts[3] };

    for( int i = 0; i < 4; i++ )
        printf("ptpts[%d] = %f\n", i, **ptpts[i]);

    return 0;
}

Output:

ptpts[0] = 2.800000
ptpts[1] = 3.700000
ptpts[2] = 4.600000
ptpts[3] = 5.500000

1 Comment

In some way yes, but that doesn't solve my problem of initialization of ptpts elements one by one (except that here it was made in one single line). If I increase the number of variables, I have to modify that line. I expected to initialize the array ptpts directly to all references of pts (and in the same time the size of ptpts would be the same as the one of pts).
0

So, thanks to the help of 0___________, I was able to find a solution which answers to my initial problem (i.e. initialize the array of pointers to pointer with either pointers or variable). In this way, I'm not using any more the intermediate array of pointer pts but create directly the array of pointers to pointer using the .

Here is the initialization part of the array ptpts:

#if ITYPE
#define ADAPT(name) pt##name
#else
#define ADAPT(name) (float *){&name}
#endif

float **ptpts[] = { &ADAPT(a), 
                    &ADAPT(b), 
                    &ADAPT(c), 
                    &ADAPT(d) };

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.