为什么-Wcast-ALIGN没有警告投从字符*为int * x86上? [英] Why does -Wcast-align not warn about cast from char* to int* on x86?

查看:1248
本文介绍了为什么-Wcast-ALIGN没有警告投从字符*为int * x86上?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,GCC有-Wcast对齐选项每当一个指针转换使得所需的目标对准增加,这警告。

I understand that gcc has an option -Wcast-align which warns whenever a pointer is cast such that the required alignment of the target is increased.

下面是我的程序:

char data[10];
int ptr = *((int *)data);

在我的机器上,数据的对齐要求是1,而它的8 PTR。

On my machine, the alignment requirement of data is 1 whereas it's 8 for ptr.

为什么我没有得到一个警告?

Why don't I get a warning?

这可能是因为我编译它在x86?

Could it be because I'm compiling it for x86?

推荐答案

编译的Linux i386或x86-64的时候,使用标准的ABI这些系统时,警告将永远不会被发出。让我来解释一下为什么会这样。

The warning will never be emitted when compiling for Linux i386 or x86-64, when using the standard ABIs for these systems. Let me explain you why that is so.

首先,让我们看看 gcc的文档有什么看法 -Wcast对齐

First, let's see what gcc's documentation has to say about -Wcast-align :

警告每当指针转换,这样的调整需要
  目标被增加。例如,警告如果的char * 被强制转换为
  为int * 在整数只能在两被访问机器或
  四字节的边界。

Warn whenever a pointer is cast such that the required alignment of the target is increased. For example, warn if a char * is cast to an int * on machines where integers can only be accessed at two- or four-byte boundaries.

使用通用的指令时,英特尔架构不需要整数对齐。从<一个报价href=\"http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-1-manual.pdf\">Intel's基本体系结构手动,章4.1.1的字,双,四字和双四字的对齐的:

The Intel architecture does not require alignment of integers when using general-purpose instructions. Quoting from Intel's Basic Architecture manual, chapter 4.1.1 Alignment of Words, Doublewords, Quadwords, and Double Quadwords :

字,双字,并将四字不需要存储器对齐
  自然边界。自然界限字,双字,
  和四字是偶数地址,地址整除
  四,和地址整除八个,分别为。
  但是,为了提高程序,数据结构的性能
  (尤其是栈)应该在自然边界,只要对齐
  可能的。

Words, doublewords, and quadwords do not need to be aligned in memory on natural boundaries. The natural boundaries for words, double words, and quadwords are even-numbered addresses, addresses evenly divisible by four, and addresses evenly divisible by eight, respectively. However, to improve the performance of programs, data structures (especially stacks) should be aligned on natural boundaries whenever possible.

对齐,因此,不是绝对必要的,但强烈建议。然而,有一例外的规则,你可能有一点。在 EFLAGS 寄存器的第18位被称为对齐检查一下,咬了 CR0 寄存器的18被称为对齐掩码标志。当它们都设置为1,任何存储器访问未在其自然边界对齐的数据(因此,第2个字节为词语,4个字节的双字,等等)导致 #AC 对齐检查异常的。如果您想了解更多关于这一点,请查看<一个href=\"http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-system-programming-manual-325384.pdf\">Intel系统编程指南。

Alignment, therefore, is not strictly necessary, though highly recommended. There is, however, one exception to that rule, which you may have had in mind. Bit 18 of the EFLAGS register is known as the "Alignment Check" bit, and bit 18 of the CR0 register is known as the "Alignment Mask" flag. When they are both set to 1, any memory accesses to data which is not aligned at its "natural boundary" (so, 2 bytes for words, 4 bytes for doublewords, and so on) results in #AC, the Alignment Check Exception. If you want to find out more about this, check out the Intel System Programming Guide.

然而,无论是 System V的ABI i386的,也不是的System V ABI的x86-64的指定该对齐标记EFLAGS中设置。事实上,在i386 ABI指出第29页以下,3-3章的人机界面的:

However, neither the System V ABI for i386, nor the System V ABI for x86-64 specify that the Alignment Flag in EFLAGS is set. In fact, the i386 ABI notes the following on page 29, chapter 3-3 Machine Interface :

英特尔386架构不要求所有的数据访问是
  正确对齐。 (......)因此,任意的数据访问,如
  指针取消引用或参考的参数,可能会或可能不会
  正确对齐。访问不对齐的数据会比慢
  访问正确对齐的数据,但在其他方面没有任何区别。

The Intel386 architecture does not require all data access to be properly aligned. (...) Consequently, arbitrary data accesses, such as pointers dereference or reference arguments, might or might not be properly aligned. Accessing misaligned data will be slower than accessing properly aligned data, but otherwise there is no difference.

虽然还建议:

编制人员应分配独立的数据对象与适当的
  对齐。

Compilers should allocate independent data objects with the proper alignment.

GCC总是知道的,它编译code平台的ABI,以及 - 86/64的情况下 - 是意识到了未对齐的数据访问允许的情况下。这就是为什么code这样编译没有有关对齐警告(让我们忘掉严格别名规则在下面的例子):

GCC always knows the ABI of the platform for which it compiles code, and - in case of x86/64 - is aware of the fact that unaligned data access is allowed. This is why code like this will compile without a warning about alignment (let's forget about strict aliasing rules in the following examples) :

int main(void)
{
    char foo[] = "foobar";
    int bar = *(int*)(foo + 1);
    return 0;
}

如果您尝试进行编译code与ARM的gcc工具,你会得到警告:

If you try to compile this code with the gcc toolchain for ARM, you will get the warning :

daniel@Jurij:/tmp$ arm-linux-gnueabi-gcc -Wcast-align align.c 
align.c: In function 'main':
align.c:4:13: warning: cast increases required alignment of target type [-Wcast-align]
  int bar = *(int*)(foo + 1);

这是因为在ARM未对齐访问通常最好避免。我不是专家ARM,所以我真的不能说什么比这更。

This is because unaligned access is generally best avoided in ARM. I'm not an ARM expert, so I really can't say anything more than that.

另外,请注意,大多数是我写的并不适用于SSE / AVX。

Also, please note that most of what I wrote does not apply to SSE/AVX.

这篇关于为什么-Wcast-ALIGN没有警告投从字符*为int * x86上?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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