标签: strict-aliasing

选择退出严格别名规则的“char”豁免

如果我有一段简单的代码,uint32_t那么它可以比使用uint8_t. 据我所知,这是因为 char 可以豁免严格的别名规则。考虑:

using T = uint32_t;

T *a;
T *b;
T *c;

void mult(int num)
{
    for (int count = 0; count < num; count++)
    {
        a[count] = b[count] * c[count];
    }
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/sW1xnTrhc

这有一个内部循环-01

.LBB0_2:                                # =>This Inner Loop Header: Depth=1
        mov     r8d, dword ptr [rcx + 4*rdi]
        imul    r8d, dword ptr [rax + 4*rdi]
        mov     dword ptr [rdx + 4*rdi], r8d
        inc     rdi
        cmp     rsi, rdi
        jne     .LBB0_2
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,它只是加载一个值,进行乘法,存储结果,然后循环。这很好。但是,如果我使用uint8_t …

c++ types simd strict-aliasing compiler-optimization

5
推荐指数
0
解决办法
142
查看次数

当内存来自 malloc 时,将 char * 转换为另一个指针类型是否会违反严格的别名规则?

读到- 以及它们char *的签名和未签名对应项 - 可以为任何类型别名,而不会违反严格的别名规则。但是,将一个char *点指向一个int变量并将其强制转换char *为 a 会double *违反规则,因为底层对象的类型为int。但如果记忆来自 呢malloc?例如:

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    void *buffer = malloc(32);
    unsigned char *ptr = buffer;

    *ptr = 10;
    *((double *)(ptr + 1)) = 3.14;
    *((double *)(ptr + 9)) = 2.718;

    printf("*ptr: %d\n", *ptr);
    printf("*(ptr + 1): %lf\n", *((double *)(ptr + 1)));
    printf("*(ptr + 9): %lf\n", *((double *)(ptr + 9)));
    
    return 0;
} …
Run Code Online (Sandbox Code Playgroud)

c strict-aliasing

5
推荐指数
1
解决办法
194
查看次数

union for uint32_t和uint8_t [4]未定义的行为?

这个答案的评论中,据说使用如下的联合将整数分割成它们的字节将是未定义的行为.在那个地方给出的代码是相似的,虽然与此不相同,请注意我是否更改了代码的未定义行为相关方面.

union addr {
 uint8_t addr8[4];
 uint32_t addr32;
};
Run Code Online (Sandbox Code Playgroud)

到目前为止,我认为这将是一个很好的做法,addr = {127, 0, 0, 1};并得到相应 uint32_t的回报.(我承认根据我的系统的字节顺序,这可能产生不同的结果.但问题仍然存在.)

这是未定义的行为吗?如果是这样,为什么?(我不知道C++中的UB是什么意思是访问非活动的联盟成员.)


C99

  • 在这一点上,C99非常接近C++ 03.

C++ 03

  • 在联合中,最多一个数据成员可以在任何时间处于活动状态,也就是说,最多一个数据成员的值可以随时存储在并集中.C++ 03,第9.5(1)节,第162页

然而

  • 如果POD-union包含几个共享一个共同初始序列的POD结构,则允许检查任何POD结构成员的公共初始序列同上.
  • 如果两个POD-struct类型具有相同数量的非静态数据成员,则它们是布局兼容的,并且相应的非静态数据成员(按顺序)具有布局兼容类型 C++ 03,第9.2(14)节,第157页
  • 如果两种类型T1和T2是相同类型,则T1和T2是布局兼容类型.C++ 03,第3.9(11)节,第53页

结论

  • as uint8_t[4]uint32_t不是同一类型(我猜,一个严格的混叠的东西)(加上两个都不是POD结构/联合)上面确实是UB?

C++ 11

  • 请注意,聚合类型不包含联合类型,因为具有联合类型的对象一次只能包含一个成员.C++ 11,脚注46,第42页

c c++ strict-aliasing unions type-punning

4
推荐指数
4
解决办法
3142
查看次数

这个简短的程序是合法的C++吗?

http://cppquiz.org上解决测试时,我发现了这段有趣的代码:

#include <iostream>

int f(int& a, int& b) {
    a = 3;
    b = 4;
    return a + b;
}

int main () {
    int a = 1;
    int b = 2;
    int c = f(a, a);// note a,a
    std::cout << a << b << c;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是这个程序是合法的C++还是不是?我担心严格的混淆.

c++ strict-aliasing

4
推荐指数
1
解决办法
209
查看次数

Berkley套接字,打破别名规则?

我问自己,我可以使用严格别名的BSD套接字,而不是通过编译gcc获得未定义的行为吗?

bind(sdListen, (struct sockaddr*)&sockaddr_inIdentifier, sizeof(sockaddr_inIdentifier))
Run Code Online (Sandbox Code Playgroud)

据我所知,这行代码打破了严格的别名规则(并且gcc给了我相同的警告).那么是否有一个计划b,在O3模式下使用套接字而不转向严格的数据?当然没有违反规定?或者我是否必须运行一个可以在所有系统/编译器上运行的套接字系统?

c sockets gcc strict-aliasing

4
推荐指数
1
解决办法
362
查看次数

`restrict`是否会影响传递指针的别名,而不是彼此

restrict添加到C99 的关键字的主要用途之一是允许编译器将某些内容加载到寄存器中,并假设寄存器将镜像这样加载的变量的状态.特定

void foo1(int * restrict a, int * restrict b) {
  (*a)++; (*b)++; (*b)+=(*a);
}
Run Code Online (Sandbox Code Playgroud)

编译器有权假设写入(*b)不会受到影响(*a),从而避免(*a)在其之后重新加载.是否restrict有混淆的任何其他影响?例如,给定:

extern void foo2a(int * restrict q);
extern void foo2b(void);
int x;
int foo2(restrict int *q) {
  int z=x;
  x++; *q++; x++;
  foo2a(&z);
  x++; *q++; z++;
  foo2b();
  x++; *q++; z++;
  return x+(*q)+z;
}
Run Code Online (Sandbox Code Playgroud)

是否需要编译器预期增加*q,调用foo2a()foo2b()可能都会受到干扰x,并且调用可能对" x和"的值"感兴趣" *q?编译器是否需要假设调用foo2a()可能持有其参数 - 即使它被标记restrict,这样foo2b()可以修改z …

c restrict strict-aliasing language-lawyer restrict-qualifier

4
推荐指数
1
解决办法
122
查看次数

是否从size_t或uintptr_t来回转换指针会破坏严格的别名?

我建议更改一个库,其公共API目前看起来像这样:

typedef size_t enh;  /* handle */

int en_open(enh *handle)
{
    struct internal *e = malloc(...);
    *handle = (enh)e;
    return 0;
}

int en_start(enh handle)
{
    struct internal *e = (struct internal*)handle;
    return do_something(e);
}
Run Code Online (Sandbox Code Playgroud)

这种用法,来回摆动以size_t打破严格的走样?

为了记录,我struct internal在公共API中提出了一个典型的不透明前向声明,如此Programmers.SE关于相同代码的问题所示.

c api-design strict-aliasing

4
推荐指数
1
解决办法
428
查看次数

如何通过其他类型重新解释数据?(打字混淆)

#include <iostream>

int main(int argc, char * argv[])
{
    int a = 0x3f800000;

    std::cout << a << std::endl;

    static_assert(sizeof(float) == sizeof(int), "Oops");

    float f2 = *reinterpret_cast<float *>(&a);

    std::cout << f2 << std::endl;

    void * p = &a;
    float * pf = static_cast<float *>(p);
    float f3 = *pf;

    std::cout << f3 << std::endl;

    float f4 = *static_cast<float *>(static_cast<void *>(&a));

    std::cout << f4 << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我从可靠的编译器中获得以下信息:

me@Mint-VM ~/projects $ g++-5.3.0 -std=c++11 -o pun pun.cpp -fstrict-aliasing -Wall
pun.cpp: In function ‘int main(int, …
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing

4
推荐指数
2
解决办法
296
查看次数

严格的别名规则可以吗?

struct Test {
    void doAction() {}
};

// Create and save into a void*
void *ptr = new Test;

// Real use through a Test*
Test *t = static_cast<Test *>(ptr);
t->doAction();

// Delete
delete static_cast<Test *>(ptr);
Run Code Online (Sandbox Code Playgroud)

ptr仅用于保存对象的地址,并且该地址仅取消引用该对象的真实类型.

所以除非它被解除引用到一个不相关的类型,否则严格的别名规则是可以的呢?

c++ strict-aliasing c++11

4
推荐指数
1
解决办法
109
查看次数

C++严格别名不可知的演员

我已经在Stack Overflow中阅读了很多关于严格别名的QA,但它们都很常见,而且讨论总是倾向于引用C++标准的深层细节,这些细节几乎总是很难理解.特别是在标准时,不要直接说话,而是用泥泞不清楚的方式描述.所以,我的问题可能是这里有大量质量保证的重复,但是,请回答一个具体的问题:

这是做"nonalias_cast"的正确方法吗?:

template<class OUT, class IN>
inline auto nonalias_cast(IN *data) {
    char *tmp = reinterpret_cast<char *>(data);
    return reinterpret_cast<OUT>(tmp);
}

float f = 3.14;
unsigned *u = nonalias_cast<unsigned *>(&f);
*u = 0x3f800000;
// now f should be equal 1.0
Run Code Online (Sandbox Code Playgroud)

我猜答案是否定的.但是有什么好的解决方法吗?当然,除了禁用严格别名标志.联盟也不是一个方便的选择,除非有一种方法在nonalias_cast函数体内部适合联合黑客.memcpy这里也不是一个选项 - 数据更改应该是同步的.

一个不可能的梦想或一个难以捉摸的现实?

UPD:

好的,既然我们得到了一个否定答案"是否可能?" 问题,我想问你一个困扰我的额外问题:

将如何解决这个任务?我的意思是有很多实际的任务,更多的是要求"玩一点点"的方法.例如,假设您必须像这样编写IEEE-754浮点转换器.我更关注问题的实际方面:如何有一个解决方法来实现目标?至少在"#$ $的痛苦"方式.

c++ strict-aliasing

4
推荐指数
2
解决办法
311
查看次数