How do I apply the constraint type keyword on arrays of struct elements?

Let's say I have struct

like below:

typedef struct MyStruct {
    double a[3];
    double b[6];
} MyStruct;

      

I am passing structures to a function to do some operations. For example:

void MyFcn(MyStruct *out, const MyStruct *in) {
    out->a[2] = in->b[5];
    /* do more stuff */
}

      

If I want to qualify array pointers MyStruct.a

and MyStruct.b

as having no overlapping memory with the constraint keyword, is there a way to do it?

Perhaps most compilers would optimize by assuming that MyStruct.a

both are MyStruct.b

pointing to a contiguous block of memory without any aliases, and there is no point in adding a delimiter? I have no idea.

I know that I could just make a and b pointers instead of arrays, like

typedef struct MyStruct {
    double *restrict a;
    double *restrict b;
} MyStruct;

      

but given the size of the arrays, this approach makes overflow debugging difficult and unnecessarily difficult to initialize variables (requires heap allocation or compound literals and assigned initializers).

EDIT

From the comments below, I need to clarify that I wanted to better describe this question with an example, and not limit it to this use case. In the responses, it turned out that structure members cannot have overlapping memory (which is what unions are for).

However, the question still remains for different functional I / O. For any number of I / O functions with different structure definitions, is the compiler optimized if there are possibilities for aliased arrays between structures? If it weren't, how do you provide the constraint keyword?

+3


source to share


3 answers


I have no limb, I have little experience with restrict

. Based on research, this seems to be correct. So make this wiki for everyone to change.


Add restrict

to function parameters (not to typedef

). By appending restrict

to a pointer, the compiler can assume that only that pointer will access / modify the data it points to. This allows the optimizations the OP wanted, since pointers don't support each other's data.

typedef struct MyStruct {
    double a[3];
    double b[6];
} MyStruct;

void MyFcn(MyStruct * restrict out, const MyStruct *restrict in);

      

So now it MyFcn()

can use when used in

and out

not point to the same data. Calling code should also never do MyFcn(&data, &data)

, as it violates the contract as calling code of dispatched pointers to overlapping memory.



Some specifications restrict

An object that is accessed by a constrained constraint has a special relationship to this pointer. This association ... requires that all calls to this object, directly or indirectly, use the value of this particular pointer. The intended use of the qualifier restrict

... is to advance optimization, ... C11dr §6.7.3 8

Types other than pointer types, whose reference type is the object type, should not be restricted. §6.7.3 2

The translator can ignore any or all of the consequences of use restrict

. §6.7.3.1 6


Even one parameter restrict

can make sense.

char buf[100];
void foo1(char * restrict p1) {
  /* foo1() knows p1 does not overlap global `buf`. */
  strcpy(buf, p1);  
}

      

0


source


"If I want to qualify the array pointers MyStruct.a and MyStruct.b ...". a

and b

- arrays (for the first typedef), not pointers and final "array pointers" - it would be something like

char a[10];
... &a ....

      

Also, if they are implicitly converted to a pointer, they cannot be aliased for the same structure . If you need different pointers, you can qualify them restrict

. However, you are not using pointers to these arrays in your example code, so you don't need to.



The only pointers that can be aliased are in

and out

. This is a matter of intended use. I would recommend not actually doing them, so you could qualify them restrict

and possibly in

additionally const

if applicable.

Btw: only pointer types can be restrict

ed
, and arrays are not pointers, but decay to them for most operations.

Oh and: If the sizes of the arrays are fixed, I agree that creating field pointers is a pointless and just plain inefficient twist.

+2


source


out->a

and in->b

may overlap if out

they in

point to different parts of the union that are offset by some amount.

Cannot be used restrict

on a struct member. And I would say that it doesn't make any sense. How will you fulfill this warranty?

It is enough to use restrict

functions for your parameters that promises that no part of one structure overlaps with another.

NB. x = y

will generate the same code no matter if x

and overlap y

.

+1


source







All Articles