【发布时间】:2020-04-27 06:38:11
【问题描述】:
我正在测试如何使用带有指针算法的数组名来访问数组 elemnets,我想出了这个程序:
#include <stdio.h>
int main(){
// definition of array using designators
int a[2][2][2] = {
[0] = {[0] = {1, 2}, [1] = {3, 4}},
[1] = {[0] = {5, 6}, [1] = {7, 8}}
};
printf("7th element (pointer): %p\n", *(*(a + 1) + 1) + 0);
printf("8th element (pointer): %p\n", *(*(a + 1) + 1) + 1);
return 0;
}
尽管程序可以正常工作并打印出所有内容:
7th element (pointer): 0x7ffd4b09a1c8
8th element (pointer): 0x7ffd4b09a1d0
我在编译时收到警告,对于我在printf() 中使用%p 占位符的每一行都说这样的话:
warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int *’ [-Wformat=]
printf("7th element (pointer): %p\n", *(*(a + 1) + 1) + 0);
~^ ~~~~~~~~~~~~~~~~~~~
%ls
所以乍一看,我必须简单地将指针转换为(void *),如果我这样做并更改行:
printf("8th element (pointer): %p\n", *(*(a + 1) + 1) + 1);
用这一行:
printf("8th element (pointer): %p\n", (void *)(*(a + 1) + 1) + 1);
我收到警告:
warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arith]
printf("8th element (pointer): %p\n", (void *)(*(a + 1) + 1) + 1);
^
编译器为第 8 个元素计算一个不同的地址,这个地址只比前面的 elemnet 的地址大 1 个字节:
7th element (pointer): 0x7ffd9e5e1bf8
8th element (pointer): 0x7ffd9e5e1bf9
我也尝试过这样修复它(又加了一个大括号):
printf("8th element (pointer): %p\n", (void *)((*(a + 1) + 1) + 1));
警告消失了,但地址的计算方式仍然不同:
7th element (pointer): 0x7ffca6c6c468
8th element (pointer): 0x7ffca6c6c470
看起来编译器需要指针类型来计算地址,如果我转换它,它不会正确计算地址。有谁知道我可以做些什么来消除警告并以正确的方式计算地址?
【问题讨论】:
-
&a[1][1][1]更容易阅读 -
这只是一个错字。您想要做的是添加
(void *)(expr),其中expr是原始代码中的表达式。您实际上所做的是删除*,然后添加演员表。 -
@DavidC.Rankin 我完全同意,但是,我对 C 的所有肠道都感兴趣。
-
不用担心,数组索引或指针表示法是完全等价的,所以任何一种方式都可以(尽管使用指针表示法
:)你会失去很多新用户 -
@DavidC.Rankin 我个人认为这不仅仅是对新用户的挑战。它也会给有经验的用户带来问题,因为像这样的符号需要更多的处理/维护来证明表达式是否正确,以及这些表达式实际上在做什么。这样一来,宝贵的时间就白白浪费了。除非它没有提供真正的好处,否则我会使用数组索引版本。
标签: c pointers multidimensional-array pointer-arithmetic