我应该担心指针铸造过程中的对齐吗? [英] Should I worry about the alignment during pointer casting?

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

问题描述

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

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. C风格的转换与 reinterpret_cast

  2. 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 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*)

一个更好的替代方法是使用 std ::如果缓冲区重叠(或者更好地 std :: memmove / 3472964rel =nofollow> 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() << '\n';
}

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风格的cast根据不同的类型做不同的事情。指针类型之间的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.


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天全站免登陆