【发布时间】:2020-08-01 11:29:58
【问题描述】:
所以,在过去的几天里,我一直在反对严格的别名规则和有效的类型规则。虽然它的精神很清楚,但我想确定对规则的良好技术理解。请注意,我已经解决了许多关于 SO 的相关问题,但我认为这里提出的问题并没有以在任何其他地方真正与我同在的方式得到回答。
这个问题分为两部分。
在第一部分,我将有效的类型规则分成句子,并解释我自己对每个句子的理解。对于其中的每一个,如果它是正确的,请验证我的理解,或者如果它有缺陷,请纠正我并解释它的原因。对于最后一个“句子”,我还提出了两个问题,希望得到答案。
问题的第二部分涉及我对特区的理解。
第 1 部分:有效的类型规则
第 1 句
访问其存储值的对象的有效类型是对象的声明类型,如果有的话。
这很清楚 - 一个声明的对象,如 int x 具有永久有效类型,即声明它的类型(在本例中为 int)。
第二句
如果通过具有非字符类型类型的左值将值存储到没有声明类型的对象中,则左值的类型将成为该访问以及后续访问的有效类型不修改存储的值。
“没有声明类型的对象”通常是动态分配的对象。
当我们将数据存储在分配的对象中时(无论它是否已经具有有效类型),对象的有效类型将成为用于访问数据以进行存储的左值的类型(除非左值是字符类型)。比如:
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
还可以更改已经具有有效类型的对象的有效类型。例如:
float* f = (float*) x;
*f = 20.5; // *x now has effective type float, because the type of lvalue *f is float.
第 3 句
如果使用 memcpy 或 memmove 将值复制到没有声明类型的对象中,或者复制为字符类型的数组,则该访问的修改对象的有效类型以及不修改该访问的后续访问value 是从中复制值的对象的有效类型(如果有的话)。
这意味着当我们给一个分配的对象设置一个值时,如果该值是通过一个与char*兼容类型的左值(或通过memcpy和memmove)设置的,那么该对象的有效类型就变成了复制到其中的数据的有效类型。例如:
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 句
对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型。
关于这部分我有两个问题:
A.通过“对于所有其他访问”,文本是否仅仅意味着“对于所有读取访问”?
在我看来,之前所有引用未声明类型对象的规则都只处理存储一个值。那么这仅仅是针对未声明类型的对象(可能已经或可能没有有效类型)的任何 read 操作的规则吗?
B.内存中的特定对象只有一种有效类型。那么 - “对于所有其他访问”的文本是什么意思......这不是访问的问题,而是对象的客观有效类型的问题。不是吗?请澄清文本的语言。
第 2 部分:关于严格别名的问题
严格的别名规则描述是这样开始的(强调我的):
一个对象的存储值只能由具有以下类型之一的左值表达式访问 [...]
当文本显示“已访问存储值”时 - 是指读写访问,还是仅读取?
作为问这个问题的另一种方式:以下代码是否构成严格别名违规或合法?
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
【问题讨论】:
标签: c language-lawyer strict-aliasing