C语言 如何在结构成员数组中应用限制指针类型关键字



假设我有一个struct定义如下:

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

我将结构传递给一个函数来执行一些操作。例如:

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

如果我想将数组指针MyStruct.aMyStruct.b限定为没有与restrict关键字重叠的内存,是否有任何方法可以做到这一点?

也许大多数编译器会优化假设MyStruct.aMyStruct.b指向连续内存块没有任何混叠,并且没有必要添加限制限定符?我不知道。

我知道我可以简单地让a和b成为指针而不是像这样的数组

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

但是考虑到数组的大小是已知的,这种方法使调试溢出变得困难,并且不必要地使变量初始化变得复杂(需要动态内存分配或复合字面量和指定初始化器)。

编辑

从下面的注释中,我需要澄清,我想让示例更好地描述问题,而不是将其约束到那个用例中。答案确实澄清了结构成员不能有重叠的内存(这就是联合的作用)。

然而,对于不同的函数输入/输出,问题仍然存在。对于具有不同结构定义的任意数量的函数输入/输出,如果结构之间存在别名数组的可能性,编译器会优化吗?如果没有,如何给出restrict关键字?

"如果我想限定数组指针MyStruct。a和MyStruct。b……"。ab是数组(对于第一个类型定义),而不是指针,也没有明确的"数组指针"——这将是类似于

的东西
char a[10];
... &a ....
同样,如果它们隐式地转换为指针,则它们不能为同一结构体别名。如果需要指向它们的不同指针,可以限定这些restrict。但是,在示例代码中不使用指向这些数组的指针,因此不需要。

可以别名的指针只有inout。这是一个有意使用的问题。我建议他们实际上不应该这样做,所以你可以将它们限定为restrictin,如果适用的话,还可以加上const

Btw:只有指针类型可以被restrict ed,数组不是指针,但在大多数操作中会衰减到指针。

哦,还有:如果数组的大小是固定的,我同意让字段成为指针是毫无意义的,只是低效的膨胀。

我在restrict方面没有什么经验。根据研究,这似乎是正确的。所以让这个wiki让所有人都可以修改


restrict添加到函数参数中(而不是typedef)。通过将restrict添加到指针上,编译器可能会认为只有该指针才能访问/更改它所指向的数据。这允许OP所期望的优化,因为指针不别名彼此的数据。

typedef struct MyStruct {
    double a[3];
    double b[6];
} MyStruct;
void MyFcn(MyStruct * restrict out, const MyStruct *restrict in);

所以现在MyFcn()可以假设在使用inout时不会指向相同的数据。调用代码也不应该执行MyFcn(&data, &data),因为这会破坏契约,因为调用代码会发送指向重叠内存的指针。

部分restrict规范

通过限制限定指针访问的对象与该指针具有特殊关联。这个协会,……要求对该对象的所有访问都直接或间接地使用该特定指针的值。restrict限定符的预期用途…是促进优化,…C11dr§6.7.3 8

引用类型为对象类型的指针类型以外的类型不受限制。§6.7.3 2

翻译人员可以自由地忽略使用restrict的任何或所有混叠含义。§6.7.3.1 6


即使一个restrict参数也可能有意义。

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

最新更新