有这种情况。
#include <stdio.h>
#include <stdlib.h>
struct Test { char c; } foo;
int main (void) {
struct Test **ar;
ar=malloc(16);
*(ar+1) = &foo;
ar[1]->c = 'c'; //this work
(*(*ar+1)).c = 'c'; //this does't work
return 0;
}
//(**(ar+1)).c='c'; --> first case
为什么上面的方法只适用于数组输入,而不是指针注销?
struct Test { char c; } foo;
int main (void) {
struct Test **ar;
ar=malloc(16);
*ar=malloc(0);
*(ar+1) = &foo;
//(**(ar+1)).c='c';
(*(*ar+1)).c='c'; // NOW IT WORKS --> second case
printf("%c\n", (*(*ar+1)).c); //prints 'c'
return 0;
}
现在即使分配了0个字节,也没有关系,因为我只是想要一个OS提供的地址,以便第一个元素被初始化。
问题:在这两种情况下,指针算术是如何工作的?
1)首先为了得到l值的? struct Test
指针直接从指向的地址出发,由 ar
到l值的方法是 **ar
- sizeof(struct Test**)
2)在第二种情况下,指针确实已经初始化了第一个成员。ar[0]
所以它从这里开始 *ar
并以 *ar
- sizeof(struct Test*)
.
但两个指针的大小是一样的 sizeof(struct Test**) == sizeof(struct Test*)
,因此不应该有算术上的差异,还是我漏掉了什么?
struct Test **ar;
ar=malloc(16);
...
(*(*ar+1)).c = 'c'; //this does't work
当然是这样。正如我在评论中所说 *
优先于 +
C 操作员优先. 那么,到底发生了什么?(*(*ar+1)).c
? 你看
(*ar+1)
这相当于:
(ar[0] + 1)
因为... 类型 对于 ar
是一个 指针对指针 struct Test
, *ar
或 ar[0]
是类型 指向 struct Test
. 然后你加 + 1
其中增加 sizeof (struct Test*)
到第一个指针 ar
这就是你想要的。
为什么这样做呢?操作符优先。
*ar /* dereference ar** leaving pointer to struct Test */
(*ar + 1) /* advance to next pointer - applied before next dereference */
*(*ar + 1) /* dereference again leaving struct Test assigned to 2nd pointer */
(*(*ar + 1)).c /* reference member 'c' of above */
可读性是至关重要的,当你使用多层次的间接性时。使用索引符号会有很大的帮助。使用索引符号会有很大帮助。(*(*ar + 1)).c = 'c';
,这样写起来就干净多了。
(*ar)[1].c = 'c';
这样可以清楚地表达出你是在引申... ar
的偏移量之前,先用 1
并再次重新引用(the [..]
提供了一个dereference,就像 '*'
来达到分配给你的第2个寄存器。
首先,你应该正确地指定分配的内存大小
ar = malloc( 2 * sizeof( struct Test * ) );
本声明
*(ar+1) = &foo;
将分配的指针数组的第二个元素设置为全局变量foo的地址。
这与
ar[1] = &foo;
这种表达方式
*ar
相当于
ar[0]
给出了分配的指针数组的第一个元素。它没有被初始化。结果这个表达式
*ar+1
或
ar[0] + 1
援引未定义的行为(在未初始化且值不确定的东西上加1)。
您的意思似乎是
(**(ar+1)).c = 'c';
这就是表达方式
*( ar + 1 )
给出了动态分配的指针数组的第二个元素。再引用它,你可以得到对象的地址。foo
. Dereferencing第二次得到对象foo本身的lvalue。
请注意,表达式
ar[1]
相当于
*( ar + 1 )
从这句话可以看出
ar[1]->c = 'c'
上述表达式产生一个指针。因此,如果你想使用操作符,你需要对它进行去引用。
**( ar + 1 )
你想去引用得到 ar[i]
,让我们做为。
(*(ar+1))->c = 'c';