指针VS C中的数组,不平凡的区别 [英] Pointer vs array in C, non-trivial difference

查看:131
本文介绍了指针VS C中的数组,不平凡的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我真正理解这一点,并重新读取标准(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屋!

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