与严格别名相关的有效类型规则 [英] Effective type rules with relation to strict aliasing

查看:63
本文介绍了与严格别名相关的有效类型规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,在过去的几天里,我一直在反对严格的别名规则和有效的类型规则.尽管其精神很明确,但我想对规则有良好的技术理解.请注意,我已经解决了许多有关SO的问题,但是我不认为这里提出的问题已经以与我真正相处的方式得到了回答.

So, I've been banging my head against the Strict Aliasing Rule and the effective type rules for the past couple of days. While the spirit of it is pretty clear, I'd like to nail down a good technical understanding of the rules. Please note I've gone through many related questions on SO, but I don't feel that the questions to be presented here have been answered in a way that really sits with me in any other place.

这个问题分为两个部分.

This question is divided into two parts.

在第一部分中,我将有效类型规则划分为句子,并解释了自己对每个规则的理解.对于每一种方法,请验证我的理解是否正确,如果有缺陷,请纠正我,并解释原因.对于最后一个句子",我还提出了两个问题,我希望能回答这些问题.

In the first part, I divide the effective type rules into sentences, and explain my own understanding of each one. For each of these, please validate my understanding if it is correct, or correct me if it's flawed and explain why it is. For the last "sentence", I also present two questions that I would appreciate answers to.

问题的第二部分涉及我对SAR的理解.

The second part of the question concerns my understanding of the SAR.

第1部分:有效的类型规则

句子1

用于访问其存储值的对象的有效类型是该对象的声明类型(如果有).

The effective type of an object for an access to its stored value is the declared type of the object, if any.

这很清楚-声明的对象(例如 int x )具有永久有效类型,该类型是用它声明的类型(在本例中为 int ).

This is pretty clear - a declared object such as int x has a permanent effective type, which is the type it is declared with (int in this case).

句子2

如果通过具有非字符类型的左值将值存储到没有声明类型的对象中,则左值的类型将成为该访问和随后执行该访问的对象的有效类型不修改存储的值.

If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value.

没有声明类型的对象"通常是动态分配的对象.

An "object having no declared type" is generally a dynamically allocated object.

当我们在分配的对象(是否已经具有有效类型)中存储数据时,对象的有效类型变为用于访问要存储的数据的左值的类型(除非左值是字符类型).例如:

When we store data inside an allocated object (whether or not it already has an effective type) the effective type of the object becomes the type of the lvalue used to access the data for storing (unless the lvalue is of character type). So for example:

int* x = malloc(sizeof(int)); // *x has no effective type yet
*x = 10; // *x has effective type int, because the type of lvalue *x is int

还可以更改已经具有有效类型的对象的有效类型.例如:

It is also possible to change the effective type of an object that already has an effective type. For example:

float* f = (float*) x;
*f = 20.5; // *x now has effective type float, because the type of lvalue *f is float.

第3句

如果使用memcpy或memmove将值复制到没有声明类型的对象中,或者将其复制为字符类型的数组,则该访问和未修改该对象的后续访问的修改对象的有效类型值是从中复制值的对象的有效类型(如果有的话).

If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one.

这意味着当我们将值设置为分配的对象时,如果该值是通过与 char * 兼容的左值(或通过 memcpy memmove ),则对象的有效类型变为复制到其中的数据的有效类型.例如:

This means that when we set a value into an allocated object, if the value is set through an lvalue of type compatible with char* (or through memcpy and memmove), the effective type of the object becomes the effective type of the data that is copied into it. For example:

int* int_array = malloc(sizeof(int) * 5); // *int_array has no effective type yet
int other_int_array[] = {10, 20, 30, 40, 50};
char* other_as_char_array = (char*) other_int_array;
for (int i = 0; i < sizeof(int) * 5; i++) {
    *((char*) int_array + i) = other_as_char_array[i];
}
// *int_array now has effective type int

句子4

对于没有声明类型的对象的所有其他访问,该对象的有效类型就是用于访问的左值的类型.

For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.

关于这部分,我有两个问题:

I have two question regarding this part:

A.文字"对于所有其他访问权限"是否仅表示对于所有读取访问权限"?

A. By "For all other accesses", does the text simply mean "for all read accesses"?

在我看来,所有以前引用未声明类型的对象的规则都只处理存储一个值.那么,这是否是针对未声明类型(可能具有或尚未具有有效类型)的对象执行任何 read 操作的规则?

It seems to me that all the previous rules that refer to objects of undeclared types, only deal with storing a value. So is this simply the rule for any read operation against an object of undeclared type (which may or may not already have an effective type)?

B.内存中的特定对象只有一种有效类型.所以-文本的含义是对于所有其他访问" ...这不是访问的问题,而是对象的客观有效类型的问题.是不是请说明文字的语言.

B. A particular object in memory only ever has one effective type. So - what does the text mean by "For all other accesses"... It's not a matter of the access, it's a matter of the objective effective type of the object. Isn't it? Please clarify the language of the text.

第2部分:关于严格混叠的问题

严格的别名规则描述开始如下(强调我的意思):

The strict aliasing rule description starts like so (emphasis mine):

对象只能通过具有以下类型之一的左值表达式来访问其存储值:[...]

当文本显示已访问存储值"时-是读访问还是写访问,还是仅读?

When the text says "stored value accessed" - does it mean both read and write accessing, or only read?

问这个问题的另一种方式:以下代码是否构成严格混叠"违反行为或合法吗?

As another way to ask this question: does the following code constitute a Strict Aliasing violation or is it legal?

int* x = malloc(sizeof(int)); // *x - no effective type yet
*x = 8; // *x - effective type int
printf("%d \n", *x); // access the int object through lvalue *x

float* f = (float*) x; // casting itself is legal
*f = 12.5; // effective type of *x changes to float - *** is this a SAR violation? ***
printf("%g \n", *f); // access the float object through lvalue *f

推荐答案

访问"表示可读写.对于所有其他访问权限"是指该段中未涉及的任何访问权限.概括地说,对已声明的未声明类型的对象的访问是:

"access" means read or write. "For all other accesses" means any accesses not already covered in that paragraph. To recap, the accesses to objects of no declared type that have been covered are:

  • 通过一个值将一个值存储到一个没有声明类型的对象中具有非字符类型的左值,
  • 不修改存储值的后续访问
  • 使用以下命令将值复制到没有声明类型的对象中memcpy或memmove
  • 或被复制为字符类型数组

因此所有读和写"的其余情况为:

So the remaining case of "all read and writes" are:

  • 通过类型为 的字符类型的左值将值存储到没有声明类型的对象中,
  • 我们没有想到的其他任何著作
  • a value is stored into an object having no declared type through an lvalue having a type that is a character type,
  • any other writes we didn't think of

在第2部分中,根据C11的文本,代码是正确的,

In part 2 the code is correct according to the text of C11 as per:

如果一个值通过一个值存储到一个没有声明类型的对象中具有非字符类型的左值,则左值的类型变为该访问的对象的有效类型

If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access

* x = 8; 通过一个具有非字符类型的左值将一个值存储到一个没有声明类型的对象中.因此,此访问的对象的有效类型是 int ,然后在6.5/7中,我们通过有效值类型 int 的左值访问对象> int .相同的推理适用于带有 float 而不是 int * f = 20.5 .

*x = 8; stores a value into an object having no declared type through an lvalue having a type that is not a character type. So the effective type of the object for this access is int, and then in 6.5/7 we have the object of effective type int being accesses by an lvalue of type int. The same reasoning applies to *f = 20.5 with float instead of int.

脚注:有很多理由认为6.5/6和/7的文本有缺陷,正如您在搜索有关该主题的其他问题时所看到的那样.人们(和编译器作者)对规则进行自己的解释.

Footnote: there are many reasons to believe the text of 6.5/6 and /7 to be defective, as you will have seen from searching other questions on the topic. People (and compiler writers) form their own interpretation of the rule .

这篇关于与严格别名相关的有效类型规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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