Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的'restrict'限定符是否可以帮助查找由于重叠块而导致的bug?_C - Fatal编程技术网

C中的'restrict'限定符是否可以帮助查找由于重叠块而导致的bug?

C中的'restrict'限定符是否可以帮助查找由于重叠块而导致的bug?,c,C,读了关键字restrict之后,我有点困惑。它似乎只是向编译器提示优化的可能性。但这并不是为了发现bug或提高语言的表达能力 正如所有旧时代的C程序员所知道的那样,有memcpy和memmove,后者承诺处理重叠区域,前者承诺不处理重叠区域 现在,您可以在函数参数、结构中编写restrict关键字,并且只需使用指针声明就可以了 但我找不到任何解释,如果代码中有这些应用程序的组合,那么这一切应该如何工作 例如: #include <stdint.h> #include <stdi

读了关键字restrict之后,我有点困惑。它似乎只是向编译器提示优化的可能性。但这并不是为了发现bug或提高语言的表达能力

正如所有旧时代的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;
}
Slice_uint8_t和const_Slice_uint8_t中的成员p都标记为受限。现在函数mm取了两个结构的实例。。。这就引出了我的问题:

在这种情况下,我能指望编译器聪明地使用这些限制修饰吗?或者它们是否会使事情变得更糟,例如引入未定义的行为

我用:gcc-std=c99-Wall-O3-o main*.c编译了所有这些,它编译时有0个警告,0个错误

我能指望编译器聪明地使用这些限制吗 在这种情况下,装饰物会使事情变得更糟吗。 通过引入未定义的行为


限制限定符主要用于授予编译器优化许可证。唯一的违反需要诊断的语言约束是,只能限定对象指针。作为一种实现质量问题,您可以希望您的编译器能够诊断出违反限制限定的情况,但实际上,没有编译器能够保证捕获所有违反限制的情况。

可以肯定,限制只会使其未定义,并允许编译器对您的代码进行无法追踪的破坏。@MichaeldOrger是的,我还担心每次运行我的代码时,代码的未定义行为都会在中国砸到一袋大米。我读了Keeksforgeks.org一节,我的初步结论是最好不要使用那个restrict关键字。除非这里有人让我相信:restrict可以让编译器获得一些优化优势,但在使用时必须非常小心。在代码审查期间,它会成为一块磁铁。。。