C 使用指针算法打印三维数组元素的指针
我正在测试如何使用数组名和指针算法来访问数组元素,我提出了以下程序:C 使用指针算法打印三维数组元素的指针,c,pointers,multidimensional-array,pointer-arithmetic,C,Pointers,Multidimensional Array,Pointer Arithmetic,我正在测试如何使用数组名和指针算法来访问数组元素,我提出了以下程序: #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("7
#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;
}
我在编译时收到警告,对我使用%p
的每一行中的printf()
因此,乍一看,我似乎必须简单地将指针投射到(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个元素计算一个不同的地址,该地址仅比前一个元素的地址大1字节:
7th element (pointer): 0x7ffd9e5e1bf8
8th element (pointer): 0x7ffd9e5e1bf9
我也试着像这样修复它(又添加了一个大括号):
警告消失了,但地址的计算方式仍然不同:
7th element (pointer): 0x7ffca6c6c468
8th element (pointer): 0x7ffca6c6c470
看起来编译器需要指针类型来计算地址,如果我强制转换它,它将无法正确计算地址。有人知道我能做些什么来删除警告并以正确的方式计算地址吗?如果您需要将算术设置为int*
,并将值视为void*
,请在执行算术后转换该值:
printf("7th element (pointer): %p\n", (void *)((int*)*(*(a + 1) + 1) + 0));
printf("8th element (pointer): %p\n", (void *)((int*)*(*(a + 1) + 1) + 1));
您可以将指针存储到单独的变量中,并将其传递给printf:
void *ptr7th = (*(*(a + 1) + 1) + 0);
void *ptr8th = (*(*(a + 1) + 1) + 1);
printf("7th element (pointer): %p\n", ptr7th);
printf("8th element (pointer): %p\n", ptr8th);
使用带有-Wall
参数的gcc 9.3.0版不会返回任何警告。&a[1][1][1]
更容易阅读,只是输入错误。您要做的是添加(void*)(expr)
,其中expr
是原始代码中的表达式。您实际做的是删除一个*
,然后添加cast.@DavidC.Rankin我完全同意,但是,我对C的所有内容都感兴趣。不用担心,数组索引或指针表示法是完全等效的,所以任何一种方法都可以(尽管您将失去许多使用指针表示法:)的新用户)
@DavidC.Rankin我个人认为这不仅仅是对新用户的挑战。这也会给有经验的用户带来问题,因为像这样的符号需要更多的处理/维护,以证明表达式是否正确,并为读者证明这些表达式实际上在做什么。这样一来,宝贵的时间就被浪费了。除非它不能提供真正的好处,否则我会选择数组索引版本。啊!很好的解决方案!非常感谢你。我也能够省略对int
的类型转换,它仍然像这样工作(void*)(*(*(a+1)+1))代码>
7th element (pointer): 0x7ffca6c6c468
8th element (pointer): 0x7ffca6c6c470
printf("7th element (pointer): %p\n", (void *)((int*)*(*(a + 1) + 1) + 0));
printf("8th element (pointer): %p\n", (void *)((int*)*(*(a + 1) + 1) + 1));
void *ptr7th = (*(*(a + 1) + 1) + 0);
void *ptr8th = (*(*(a + 1) + 1) + 1);
printf("7th element (pointer): %p\n", ptr7th);
printf("8th element (pointer): %p\n", ptr8th);