我正在阅读库(QNNPack)的源代码,并注意到这一行(https://github.com/pytorch/QNNPACK/blob/24d57f21503ba8ab0f8bb5d24148754a91266b9c/src/q8gemm/6x4-neon.c#L23):
void funcName(...,
const union some_union_type some_union_arg[restrict static 1]) {
// ...
}
我通常会理解关键字restrict
和static
,但是恐怕我不知道其背后的原因。我在Google上找不到任何东西,也许我搜索错误。
我猜这里是一种告诉编译器此指针指向单个对象的方法。但是我缺乏优化知识,无法进一步解释。
谢谢!
答案 0 :(得分:2)
static
根据C标准具有以下含义:
6.7.6.3函数声明符(包括原型)
7 ...如果关键字static也出现在 数组类型派生,然后对于每次调用该函数, 相应实际参数的值应提供对 数组的第一个元素,其大小至少与size表达式指定的元素相同。
这是程序的语义要求。如果函数的调用者不支持该函数,则该行为是未定义的,并且必须修复一个错误。由于指定的大小为1
,因此这意味着该函数希望有一个指向单个union some_union_type
对象的有效指针,并传递NULL
本身是未定义的行为。
这是一种在原型中指定所传递的指针必须有效的方法。编译器可以在理论上利用此信息并在传递null时发出警告。在实践中,此文档显式地记录了对该参数的要求,并且该函数甚至可以选择在访问该指针之前不检查该指针是否有效(因为它在其原型中所指定的协定要求有效的指针)。< / p>
指针上的restrict
限定符意味着函数假定指针是直接或间接访问此数据的唯一方法。因此,例如,如果要向其传递在其实现中访问的全局对象的地址,则该行为将是不确定的。这种假设有助于编译器在某些地方进行优化。
答案 1 :(得分:1)
关于您示例中static
的用法,我们有this:
将参数声明为“类型数组”调整为“类型的合格指针”,其中类型限定符(如果有)是在数组类型派生的[和]中指定的那些。如果关键字
static
也出现在数组类型派生的[和]中,则对于函数的每次调用,相应的实际参数的值均应提供对数组第一个元素的访问,且至少为大小表达式指定的许多元素。
关于您示例中restrict
的用法,我们有this:
在函数声明中,关键字
restrict
可能出现在用于声明函数参数数组类型的方括号内 。它限定将数组类型转换为的指针类型:void f(int m, int n, float a[restrict m][n], float b[restrict m][n]); void g12(int n, float (*p)[n]) { f(10, n, p, p+10); // OK f(20, n, p, p+10); // possibly undefined behavior (depending on what f does) }
结合以上示例:
void funcName(...,
const union some_union_type some_union_arg[restrict static 1]) {
// ...
}
表示,每当调用funcName
时,传递的参数(some_union_arg
)将具有至少1个元素,该函数将可以访问该元素,并且通过restrict
进行此访问{1}}已被转换为指针。