Может ли спецификатор restrict в C помочь найти ошибки из-за перекрывающихся блоков? - PullRequest
2 голосов
/ 15 мая 2019

Прочитав ключевое слово 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 ошибок.

1 Ответ

4 голосов
/ 15 мая 2019

Могу ли я ожидать, что компилятор будет умным и использовать эти restrict украшения в таком случае, или они делают вещи еще хуже (например, введя неопределенное поведение)?

Спецификатор restrict служит главным образом для предоставления лицензии компиляторам на оптимизацию. Единственным языком ограничение (нарушение которого требует диагностики) является то, что только указатели объекта могут быть restrict -квалифицированными. Что касается качества реализации, вы можете надеяться, что ваш компилятор будет диагностировать нарушения ограничивающей квалификации, но на практике ни один компилятор не может гарантировать, что он обнаружит все нарушения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...