Прочитав ключевое слово 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
изд.И теперь функция mm
берет 2 экземпляра этих структур ... и это поднимает мой вопрос:
Могу ли я ожидать, что компилятор будет умным и использовать такие украшения restrict
в таком случае, или оничто еще хуже (например, введя неопределенное поведение)?
Я скомпилировал все это с помощью: gcc -std=c99 -Wall -O3 -o main *.c
и скомпилировал 0 предупреждений, 0 ошибок.