我应该担心指针投射期间的对齐吗? [英] Should I worry about the alignment during pointer casting?

查看:31
本文介绍了我应该担心指针投射期间的对齐吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我们有一段这样的代码:

In my project we have a piece of code like this:

// raw data consists of 4 ints
unsigned char data[16];
int i1, i2, i3, i4;
i1 = *((int*)data);
i2 = *((int*)(data + 4));
i3 = *((int*)(data + 8));
i4 = *((int*)(data + 12));

我与我的技术负责人谈过,此代码可能不可移植,因为它试图将 unsigned char* 转换为通常具有更严格对齐的 int*要求.但是技术负责人说没关系,大多数编译器在转换后保持相同的指针值,我可以像这样编写代码.

I talked to my tech lead that this code may not be portable since it's trying to cast a unsigned char* to a int* which usually has a more strict alignment requirement. But tech lead says that's all right, most compilers remains the same pointer value after casting, and I can just write the code like this.

坦率地说,我不太相信.经过研究,我发现有些人反对使用上述的指针转换,例如 这里此处.

To be frank, I'm not really convinced. After researching, I find some people against use of pointer castings like above, e.g., here and here.

这里是我的问题:

  1. 在实际项目中转换后取消引用指针真的安全吗?
  2. C 风格的转换和 reinterpret_cast 之间有什么区别吗?
  3. C 和 C++ 之间有什么区别吗?

推荐答案

1.在实际项目中转换后取消引用指针真的安全吗?

1. Is it REALLY safe to dereference the pointer after casting in a real project?

如果指针碰巧没有正确对齐,它确实会导致问题.我亲眼看到并修复了由将 char* 转换为更严格对齐的类型而导致的实际生产代码中的总线错误.即使您没有收到明显的错误,您也可能遇到不太明显的问题,例如性能下降.严格遵循标准以避免 UB 是一个好主意,即使您没有立即看到任何问题.(代码违反的一项规则是严格的别名规则,§ 3.10/10*)

If the pointer happens to not be aligned properly it really can cause problems. I've personally seen and fixed bus errors in real, production code caused by casting a char* to a more strictly aligned type. Even if you don't get an obvious error you can have less obvious issues like slower performance. Strictly following the standard to avoid UB is a good idea even if you don't immediately see any problems. (And one rule the code is breaking is the strict aliasing rule, § 3.10/10*)

如果缓冲区重叠(或者更好的是 bit_cast<>())

A better alternative is to use std::memcpy() or std::memmove if the buffers overlap (or better yet bit_cast<>())

unsigned char data[16];
int i1, i2, i3, i4;
std::memcpy(&i1, data     , sizeof(int));
std::memcpy(&i2, data +  4, sizeof(int));
std::memcpy(&i3, data +  8, sizeof(int));
std::memcpy(&i4, data + 12, sizeof(int));

有些编译器比其他编译器更努力地确保 char 数组的对齐比必要的更严格,因为程序员经常会犯这个错误.

Some compilers work harder than others to make sure char arrays are aligned more strictly than necessary because programmers so often get this wrong though.

#include <cstdint>
#include <typeinfo>
#include <iostream>

template<typename T> void check_aligned(void *p) {
    std::cout << p << " is " <<
      (0==(reinterpret_cast<std::intptr_t>(p) % alignof(T))?"":"NOT ") <<
      "aligned for the type " << typeid(T).name() << '
';
}

void foo1() {
    char a;
    char b[sizeof (int)];
    check_aligned<int>(b); // unaligned in clang
}

struct S {
    char a;
    char b[sizeof(int)];
};

void foo2() {
    S s;
    check_aligned<int>(s.b); // unaligned in clang and msvc
}

S s;

void foo3() {
    check_aligned<int>(s.b); // unaligned in clang, msvc, and gcc
}

int main() {
    foo1();
    foo2();
    foo3();
}

http://ideone.com/FFWCjf

2.C 风格的强制转换和 reinterpret_cast 之间有什么区别吗?

2. Is there any difference between C-style casting and reinterpret_cast?

这取决于.C 风格的强制转换根据所涉及的类型做不同的事情.指针类型之间的 C 样式转换将导致与 reinterpret_cast 相同的结果;参见 § 5.4 显式类型转换(转换符号) 和 § 5.2.9-11.

It depends. C-style casts do different things depending on the types involved. C-style casting between pointer types will result in the same thing as a reinterpret_cast; See § 5.4 Explicit type conversion (cast notation) and § 5.2.9-11.

3.C 和 C++ 有什么区别吗?

3. Is there any difference between C and C++?

只要您处理的是 C 中合法的类型,就不应该存在.

There shouldn't be as long as you're dealing with types that are legal in C.

* 另一个问题是 C++ 没有指定从一种指针类型转换为具有更严格对齐要求的类型的结果.这是为了支持甚至无法表示未对齐指针的平台.然而,当今的典型平台可以表示未对齐的指针,并且编译器将此类转换的结果指定为您所期望的.因此,此问题是别名违规的次要问题.见[expr.reinterpret.cast]/7.

* Another issue is that C++ does not specify the result of casting from one pointer type to a type with stricter alignment requirements. This is to support platforms where unaligned pointers cannot even be represented. However typical platforms today can represent unaligned pointers and compilers specify the results of such a cast to be what you would expect. As such, this issue is secondary to the aliasing violation. See [expr.reinterpret.cast]/7.

这篇关于我应该担心指针投射期间的对齐吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆