指针VS C中的数组,不平凡的区别 [英] Pointer vs array in C, non-trivial difference
问题描述
我想我真正理解这一点,并重新读取标准(ISO 9899:1990)恰恰印证了我的明显错误的理解,所以现在我在这里问
I thought I really understood this, and re-reading the standard (ISO 9899:1990) just confirms my obviously wrong understanding, so now I ask here.
下面的程序崩溃:
#include <stdio.h>
#include <stddef.h>
typedef struct {
int array[3];
} type1_t;
typedef struct {
int *ptr;
} type2_t;
type1_t my_test = { {1, 2, 3} };
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
type1_t *type1_p = &my_test;
type2_t *type2_p = (type2_t *) &my_test;
printf("offsetof(type1_t, array) = %lu\n", offsetof(type1_t, array)); // 0
printf("my_test.array[0] = %d\n", my_test.array[0]);
printf("type1_p->array[0] = %d\n", type1_p->array[0]);
printf("type2_p->ptr[0] = %d\n", type2_p->ptr[0]); // this line crashes
return 0;
}
相比前任pressions my_test.array [0]
和 type2_p-&GT; PTR [0]
根据标准的我的间pretation:
Comparing the expressions my_test.array[0]
and type2_p->ptr[0]
according to my interpretation of the standard:
6.3.2.1数组下标
6.3.2.1 Array subscripting
的下标的定义
运算符[]是E1 [E2]是
相同(*((E1)+(E2)))
"The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))."
应用这给:
my_test.array[0]
(*((E1)+(E2)))
(*((my_test.array)+(0)))
(*(my_test.array+0))
(*(my_test.array))
(*my_test.array)
*my_test.array
type2_p->ptr[0]
*((E1)+(E2)))
(*((type2_p->ptr)+(0)))
(*(type2_p->ptr+0))
(*(type2_p->ptr))
(*type2_p->ptr)
*type2_p->ptr
type2_p-&GT; PTR
的类型为指针为int和值是 my_test
的起始地址。 * type2_p-方式&gt; PTR
因此计算结果为一个整数对象,其存储在同一地址 my_test
有
type2_p->ptr
has type "pointer to int" and the value is the start address of my_test
. *type2_p->ptr
therefore evaluates to an integer object whose storage is at the same address that my_test
has.
另外:
6.2.2.1左值,数组和功能指示器
6.2.2.1 Lvalues, arrays, and function designators
除了当它的操作数
sizeof操作符或者一元和放大器;
操作者,...,具有一个左值
type类型阵列
转换为
一个前pression型指针
它指向初始
键入
数组对象和元素不是
左值。
"Except when it is the operand of the
sizeof operator or the unary &
operator, ... , an lvalue that has
type array of type
is converted to
an expression with type pointer to
type
that points to the initial
element of the array object and is not
an lvalue."
my_test.array
的类型为int数组,是上述转换为指向int的指针与作为值的第一个元素的地址描述。因此, * my_test.array
计算为一个整数对象,其存储是在同一地址,该数组中的第一个元素。
my_test.array
has type "array of int" and is as described above converted to "pointer to int" with the address of the first element as value. *my_test.array
therefore evaluates to an integer object whose storage is at the same address that the first element in the array.
最后
6.5.2.1结构和联合说明符
6.5.2.1 Structure and union specifiers
一个指针结构对象,
适当的转换,指向其
最初的成员......,反之亦然。
有可能是内填充无名
结构对象,而不是在它的
开始,根据需要以达到
适当的调整。
A pointer to a structure object, suitably converted, points to its initial member ..., and vice versa. There may be unnamed padding within a structure object, but not at its beginning, as necessary to achieve the appropriate alignment.
由于第一个成员 type1_t
是数组的起始地址
该和整个 type1_t
目的是与上述相同。
PTR 的计算结果为,因此该 * type2_p-&GT我的理解是
一个整数,其存储在同一地址,第一
在阵列中,因此元素是相同的 * my_test.array
。
Since the first member of type1_t
is the array, the start address of
that and the whole type1_t
object is the same as described above.
My understanding were therefore that *type2_p->ptr
evaluates to
an integer whose storage is at the same address that the first
element in the array and thus is identical to *my_test.array
.
但是,这不能的情况下,因为程序一致地崩溃
在Solaris下,cygwin和linux用gcc版本2.95.3,3.4.4
4.3.2和,所以任何环境问题是完全不可能的。
But this cannot be the case, because the program crashes consistently on solaris, cygwin and linux with gcc versions 2.95.3, 3.4.4 and 4.3.2, so any environmental issue is completely out of the question.
我的推理错误/我该怎么不明白?
我如何申报type2_t使PTR指向数组的第一个成员?
Where is my reasoning wrong/what do I not understand? How do I declare type2_t to make ptr point to the first member of the array?
推荐答案
数组是一种类型的存储。在语法上,它作为一个指针,但在物理上,有一个在该结构没有指针变量 - 只是三个整数。另一方面中,int指针存储在所述结构的实际数据类型。因此,当你执行转换,你可能* PTR决策采取的第一个元素的数组中的值,即1。
An array is a kind of storage. Syntactically, it's used as a pointer, but physically, there's no "pointer" variable in that struct — just the three ints. On the other hand, the int pointer is an actual datatype stored in the struct. Therefore, when you perform the cast, you are probably* making ptr take on the value of the first element in the array, namely 1.
*我不知道这其实是定义的行为,但是这怎么会至少在最常见的系统上运行。
*I'm not sure this is actually defined behavior, but that's how it will work on most common systems at least.
这篇关于指针VS C中的数组,不平凡的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!