c-用指向指针的指针限制限定符的放置



这里有两个C和POSIX函数,它们需要从缓冲区中提取一些数据或将一些数据放入缓冲区,并告诉调用方多少数据,因此它们会获取一个指向起始缓冲区地址的指针,并在返回时将调整后的指针写在那里:

size_t mbstowcs(wchar_t *restrict pwcs, const char *restrict s,
size_t n); /* for comparison */
size_t mbsrtowcs(wchar_t *restrict dst, const char **restrict src,
size_t len, mbstate_t *restrict ps);
size_t mbsnrtowcs(wchar_t *restrict dst, const char **restrict src,
size_t nmc, size_t len, mbstate_t *restrict ps);
size_t iconv(iconv_t cd,
char **restrict inbuf, size_t *restrict inbytesleft,
char **restrict outbuf, size_t *restrict outbytesleft);

我认为缓冲区上的限制限定符的(主要(含义是,这些函数假设输入和输出缓冲区不重叠;而对于CCD_ 1(仅按值获取缓冲区地址(,情况似乎确实如此。

但是,为什么其余的函数采用ELEMENT **restrict指针而不采用ELEMENT *restrict *ELEMENT *restrict *restrict指针呢?对我来说,这些书面声明意味着缓冲区地址,存储在内存中的ELEMENT *本身,不能别名,这……可能有点帮助,是的,但不是那么重要吗?这些声明使它看起来像代码

iconv_t cd = /* ... */;
char data[] = /* ... */, *inp = data, *outp = data;
size_t inn = sizeof data, outn = sizeof data;
iconv(cd, &inp, &inn, &outp, &outn);

是有效的,这肯定不是目的吗?


在C17第6.7.3.1款(restrict的正式定义(第4段中,我们可以找到一段似乎模糊相关的内容:

[…L]etL是具有&L基于P[限制限定指针]。如果L用于访问其指定的对象X的值,并且X也被修改(通过任何方式(,则以下要求适用:T不应为常量限定。用于访问X值的每个其他左值的地址也应基于P[如前一段所定义]就本款而言,修改X的每一次访问也应被视为修改P[斜体字矿]。[…]

但我一辈子都搞不清那个斜体句子的重要性。

将限制限定符应用于地址不被占用的自动持续时间的独立对象之外的任何对象的语义充其量都是模糊的。restrict限定符在其语义最清晰的情况下提供了最大的价值,并且在基于它执行优化所需的工作量将超过此类优化的好处的情况下,编译器可以有效地忽略该限定符。在语义模糊、回报率低的情况下使用限定符充其量是浪费时间,因为编译器可能会忽略它,如果不忽略它,他们可能会以与程序员预期相反的方式进行解释。

最新更新