gpt4 book ai didi

c - C中的指针与数组,非平凡的区别

转载 作者:太空狗 更新时间:2023-10-29 16:43:02 26 4
gpt4 key购买 nike

我以为我真的理解了这一点,重新阅读标准(ISO 9899:1990)恰恰证实了我明显错误的理解,所以现在我在这里问。

以下程序崩溃:

#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;
}

根据我对标准的解释,比较表达式 my_test.array[0]type2_p->ptr[0]:

6.3.2.1 Array subscripting

"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->ptr 的类型为“指向 int 的指针”,值是 my_test 的起始地址。 *type2_p->ptr 因此计算为一个整数对象,其存储在与 my_test 相同的地址。

进一步:

6.2.2.1 Lvalues, arrays, and function designators

"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 因此计算为整数对象,其存储地址与数组中的第一个元素相同。

最后

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 对象与上面描述的相同。因此,我的理解是 *type2_p->ptr 的计算结果为一个整数,其存储在与第一个相同的地址数组中的元素,因此与 *my_test.array 相同。

但事实并非如此,因为程序一直崩溃在 solaris、cygwin 和 linux 上,gcc 版本 2.95.3、3.4.4和4.3.2,所以任何环境问题都是完全不可能的。

我的推理哪里错了/我不明白什么?如何声明 type2_t 以使 ptr 指向数组的第一个成员?

最佳答案

如果我在您的分析中有任何遗漏,请原谅我。但我认为这一切的根本错误在于这个错误的假设

type2_p->ptr has type "pointer to int" and the value is the start address of my_test.

没有什么能使它具有那个值(value)。相反,它很可能指向某处

0x00000001

因为您所做的是将构成该整数数组的字节解释为指针。然后你向它添加一些东西并下标。

此外,我非常怀疑您对其他结构的强制转换实际上是有效的(如保证有效)。如果它们都是 union 的成员,则您可以强制转换然后读取任一结构的公共(public)初始序列。但是它们不在您的示例中。您也可以转换为指向第一个成员的指针。例如:

typedef struct {
int array[3];
} type1_t;

type1_t f = { { 1, 2, 3 } };

int main(void) {
int (*arrayp)[3] = (int(*)[3])&f;
(*arrayp)[0] = 3;
assert(f.array[0] == 3);
return 0;
}

关于c - C中的指针与数组,非平凡的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/660752/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com