标签: strict-aliasing

允许施放(双*)到(双**)?

因为我在讨论中被告知"通过不兼容的指针类型进行别名是未定义的行为"(例如,double d; int *p = (int *)&d;以下问题:

它是否允许转换(double *)(double **),例如double *d1; double **d2 = &d2 使用类似于d2[0][y]期望的语法d1[y]

我知道它不是通过不兼容的指针类型完全混淆,但是我不确定.背景是我想要一个在二维数组(=图像)上运行的函数,但我希望能够只传递图像的一行或一列.

c++ pointers casting strict-aliasing undefined-behavior

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

struct数组的别名为int

struct test
{
    char member1;
    char member2;
};

int main(void)
{
    struct test structure[] = {'h', 'i'};
    static void* p = &structure;

    printf("%i", *((int*)p));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我们都知道structure应该指向struct中第一个元素的地址.为什么通过这样取消引用它,它会返回地址本身呢?

c arrays pointers strict-aliasing

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

快速strlen功能vs别名规则

我发现这个 "快速strlen函数"实现:

// for x86 only
size_t my_strlen(const char *s) {
    size_t len = 0;
    for(;;) {
        unsigned x = *(unsigned*)s;
        if((x & 0xFF) == 0) return len;
        if((x & 0xFF00) == 0) return len + 1;
        if((x & 0xFF0000) == 0) return len + 2;
        if((x & 0xFF000000) == 0) return len + 3;
        s += 4, len += 4;
    }
}
Run Code Online (Sandbox Code Playgroud)

这里使用的优化技术显然很简单:通过自然CPU字读取内存(代码是旧的并假定为x32 CPU),而不是简单的字节.

但是这段代码违反了别名规则,因此会导致未定义的行为,这些行为可以由编译器自由优化(那些使代码更快,但是更多).

我现在也看到它不可移植,因为它与little-endian endianness有关.

或者可能是我完全错了,上面的代码是正确的?这对C来说是否正确?对于C++?

c c++ type-conversion strict-aliasing strlen

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

违反严格别名,即使没有任何演员?

我想我真的在问:别名是"传递性的"吗?如果编译器知道A可能是别名B,而B可能是别名C,那么肯定它应该记住A可能因此别名C.也许这个"明显的"传递逻辑不是必需的吗?

一个例子,为了清楚起见.对我来说,最有趣的例子是严格别名问题:

// g++    -fstrict-aliasing -std=c++11 -O2
#include <iostream>

union
{   
    int i;
    short s;
} u;
int     * i = &u.i;

int main()
{   

    u.i = 1; // line 1
    *i += 1; // line 2

    short   & s =  u.s;
    s += 100; // line 3

    std::cout
        << " *i\t" <<  *i << std::endl // prints 2
        << "u.i\t" << u.i << std::endl // prints 101
        ;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

克++ 5.3.0,在x86_64(但不铛3.5.0)给出上面的输出,其中*iu.i给予不同的号码.但是它们应该给出完全相同的数字,因为它i被定义为 …

c++ strict-aliasing

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

严格别名是否会阻止您通过其他类型写入char数组?

我的理解是在Basic.lval 11中定义了C++中的严格别名:

(11)如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:

  • (11.1)对象的动态类型,
  • (11.2)对象的动态类型的cv限定版本,
  • (11.3)与对象的动态类型类似的类型(在conv.qual中定义),
  • (11.4)与对象的动态类型对应的有符号或无符号类型的类型,
  • (11.5)一种类型,它是有符号或无符号类型,对应于对象动态类型的cv限定版本,
  • (11.6)聚合或联合类型,包括其元素或非静态数据成员中的上述类型之一(递归地,包括子聚合或包含联合的元素或非静态数据成员),
  • (11.7)一种类型,它是对象的动态类型的(可能是cv限定的)基类类型,
  • (11.8)一个char,unsigned charstd?::?byte类型.

通过我的阅读,每11.8,这总是合法的,因为程序x通过类型的glvalue 访问存储的值unsigned char:

int x = 0xdeadbeef;
auto y = reinterpret_cast<unsigned char*>(&x);
std::cout << y[1];
Run Code Online (Sandbox Code Playgroud)

我很好奇使用指向别名的指针unsigned char:

alignas(int) unsigned char[4] x;
auto y = reinterpret_cast<int*>(x);
*y = 0xdeadbeef;
Run Code Online (Sandbox Code Playgroud)

这是违反严格别名的吗?我的阅读是它不是,但我只是在另一个线程上被告知它是.仅对于basic.lval,在我看来没有UB,因为程序不会尝试访问存储的值:它存储一个新的而不读取它,只要后续读取使用x,就不会发生违规.

c++ strict-aliasing language-lawyer

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

将 double 传递给 void * 参数的方法

我的问题是由于需要double通过void *函数参数正确传递变量。我问,因为在我的机器sizeof(void *)4,和sizeof(double)8,铸造一个到另一个好像它应该产生一个问题,但我的编译器(CLANG,对所有的警告)没有给出一个问题的指示,和代码似乎工作美好的。

请注意,我已经看到了这个这个。他们的标题中有相似的组成词,但没有回答这个特定的问题。

以下是否会导致严格的别名违规错误?或未定义的行为?

// some calling function
double a = 0.000234423;
func1(&a);

...

void func1(void *var)
{
    double a = *(double *)(var);
}
Run Code Online (Sandbox Code Playgroud)

c strict-aliasing

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

避免哈希函数中的严格别名冲突

如何避免严格别名规则违规,试图修改char*sha256函数的结果.

计算哈希值:

std::string sha = sha256("some text");
const char* sha_result = sha.c_str();
unsigned long* mod_args = reinterpret_cast<unsigned long*>(sha_result);
Run Code Online (Sandbox Code Playgroud)

得到2个64位:

unsigned long a = mod_args[1] ^ mod_args[3] ^ mod_args[5] ^ mod_args[7];
unsigned long b = mod_args[0] ^ mod_args[2] ^ mod_args[4] ^ mod_args[6]; 
Run Code Online (Sandbox Code Playgroud)

而不是通过concat获得结果两件:

unsigned long long result = (((unsigned long long)a) << 32) | b;
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing

0
推荐指数
1
解决办法
163
查看次数

这种严格别名规则违规是否会产生我期望的行为?

我知道违反严格别名规则是根据C标准的未定义行为.请不要告诉我这是UB,没有什么可谈的.

我想知道下面的代码是否有编译器没有预期的行为(由我在下面定义).

假设的大小floatint为4个字节,并且大端机.

float f = 1234.567;  /* Any value here */
unsigned int u = *(unsigned int *)&f;
Run Code Online (Sandbox Code Playgroud)

我在英语单词中的预期行为是"获取float存储的四个字节并按int 原样放入".在代码中它将是这个(我认为这里没有UB):

float f = 1234.567;  /* Any value here */
unsigned char *p = (unsigned char *)&f;
unsigned int u = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
Run Code Online (Sandbox Code Playgroud)

我也欢迎实际和具体的例子,为什么,除了按照标准的UB,编译器会有我认为是意想不到的行为.

c strict-aliasing undefined-behavior

0
推荐指数
1
解决办法
94
查看次数

严格混叠规则是否适用于函数调用?

关于下面的示例,在中f1,不会发生别名,因为pvoid*)无法访问,并且p1是访问内存的唯一指针。但是,p1float*)和p2int*)之间的指针别名在outside之外f1
我的问题是,此别名是否合法,也就是说,严格混叠规则是否适用于函数调用?

如果此示例有效,那么如果f1内联了该怎么办?

void f1(void *p)
{
  auto* p1 = static_cast<float*>(p);
  *p1 = 1.f;
}

int f2()
{
  int x = 1;
  auto* p2 = &x;
  f1(&x);
  *p2 = 1;
  return *p2;
}
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing language-lawyer

0
推荐指数
1
解决办法
114
查看次数

有没有合法的方法将unsigned char指针转换为std :: byte指针?

我使用STB库将图像加载到内存中.特定函数stbi_load返回指向a的指针unsigned char,该指针是一个数组.

我很想将新的C++ 17 API用于原始数据,std::byte这将使我更具表现力,让我逐个像素地对原始数据进行别名,或者通过将其转换为不同的数据类型来逐个颜色(不同大小的整数).

现在我尝试了这个:

std::unique_ptr<std::byte[], stbi_deleter>(stbi_load(...));
Run Code Online (Sandbox Code Playgroud)

当然,由于缺乏隐式转换,它不起作用.

然后我尝试了:

std::unique_ptr<std::byte[], stbi_deleter>(
  static_cast<std::byte*>(stbi_load(...))
);
Run Code Online (Sandbox Code Playgroud)

同样,它仍然没有奏效.我不得不决定使用reinterpret_cast.并让我怀疑这种转换是否合法.我unsigned char*可以std::byte* 根据严格的别名规则合法地转换为?然后我可以将数据转换为另一种数据类型std::uint32_t*并进行变异吗?这会破坏别名规则吗?

c++ casting bytebuffer strict-aliasing

-1
推荐指数
1
解决办法
193
查看次数