在阅读了关键字restrict
之后,我有点困惑。它似乎仅向编译器提示优化的可能性。但是寻找错误或提高语言的表达能力不是很多。
众所周知,过去的C程序员中有memcpy()
和memmove()
,这两个中的后者承诺处理重叠区域,前者承诺不处理重叠区域。
现在,您可以在函数参数的结构中编写restrict
关键字,并且只需使用指针声明即可单独使用。
但是我找不到任何解释,如果您的代码中包含这些应用程序的组合,那一切应该如何工作。
示例:
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define SUCCESS 1
#define FAILED 0
typedef int Ret_t;
Ret_t check( Ret_t result, const char * expr, int line, const char * file )
{
if(FAILED == result)
printf("Expr: %s failed! (%s:%d)\n", expr, file,line);
return result;
}
#define CHECK(expr) (check(expr,#expr))
#define CHECK_ABORT(expr) if(FAILED == check((expr),#expr,__LINE__,__FILE__)) return FAILED
#define CHECK_ABORT_MAIN(expr) if(FAILED == check((expr),#expr,__LINE__,__FILE__)) return -1
#define ARRAY_CAPACITY(x) (sizeof(x) / sizeof((x)[0]))
typedef struct Slice_uint8_tag
{
uint8_t * restrict p;
size_t capacity;
} Slice_uint8_t;
typedef struct const_Slice_uint8_tag
{
const uint8_t * restrict p;
size_t size;
} const_Slice_uint8_t;
static inline
Slice_uint8_t
make_Slice_uint8 (uint8_t* restrict p,size_t capacity)
{
Slice_uint8_t s = { .p = p, .capacity = capacity };
return s;
}
static inline
const_Slice_uint8_t
make_const_Slice_uint8 (const uint8_t *restrict p, size_t size)
{
const_Slice_uint8_t s = { .p = p, .size = size };
return s;
}
Ret_t mm(Slice_uint8_t target, const_Slice_uint8_t source)
{
if(target.capacity >= source.size)
{
size_t i;
for(i = 0; i < source.size; ++i)
{
target.p[i] = source.p[i];
}
return SUCCESS;
}
return FAILED;
}
int main()
{
const char hello[] = "Hello World!";
unsigned char buffer[100];
unsigned char buffer1[100];
printf("hello array length: %ld\nlength of hello string: %ld\n", ARRAY_CAPACITY(hello), strlen(hello));
CHECK_ABORT_MAIN(mm(make_Slice_uint8(buffer,ARRAY_CAPACITY(buffer)),make_const_Slice_uint8((const uint8_t*)hello,strlen(hello) + 1)));
printf( "buffer after mm(): %s\n", buffer);
CHECK_ABORT_MAIN(mm(make_Slice_uint8(buffer1,ARRAY_CAPACITY(buffer1)),make_const_Slice_uint8(buffer,ARRAY_CAPACITY(buffer))));
printf( "buffer1 after mm(): %s\n", buffer1);
// Now, lets see if `restrict` wins us something:
CHECK_ABORT_MAIN(mm(make_Slice_uint8(buffer1,ARRAY_CAPACITY(buffer1)),make_const_Slice_uint8(buffer1,ARRAY_CAPACITY(buffer1))));
printf( "buffer1 after mm(): %s\n", buffer1);
return 0;
}
p
和Slice_uint8_t
中的成员const_Slice_uint8_t
被标记为restrict
ed。现在函数mm
接受了这些结构的2个实例...这引起了我的问题:
在这种情况下,我可以期望编译器是聪明的并且使用那些restrict
装饰吗?还是会使情况变得更糟(例如,通过引入未定义的行为)?
我用gcc -std=c99 -Wall -O3 -o main *.c
编译了所有内容,并用0条警告,0条错误进行了编译。
答案 0 :(得分:4)
我可以期望编译器更聪明并使用那些
restrict
吗? 在这种情况下装饰或使事情变得更糟(例如 通过引入未定义的行为)?
restrict
限定符主要用于为编译器提供优化许可。唯一的语言 constraint (约束违例需要诊断)是只有对象指针可以是restrict
限定的。从实现的质量考虑,您可以希望编译器能够诊断出违反限制条件的情况,但是实际上,没有编译器可以保证捕获所有违反情况。