【问题标题】:Printing a pointer of an 3D array element using pointer arithmetics使用指针算法打印 3D 数组元素的指针
【发布时间】: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

看起来编译器需要指针类型来计算地址,如果我转换它,它不会正确计算地址。有谁知道我可以做些什么来消除警告并以正确的方式计算地址?

【问题讨论】:

  • &amp;a[1][1][1] 更容易阅读
  • 这只是一个错字。您想要做的是添加(void *)(expr),其中expr 是原始代码中的表达式。您实际上所做的是删除 *,然后添加演员表。
  • @DavidC.Rankin 我完全同意,但是,我对 C 的所有肠道都感兴趣。
  • 不用担心,数组索引或指针表示法是完全等价的,所以任何一种方式都可以(尽管使用指针表示法:) 你会失去很多新用户
  • @DavidC.Rankin 我个人认为这不仅仅是对新用户的挑战。它也会给有经验的用户带来问题,因为像这样的符号需要更多的处理/维护来证明表达式是否正确,以及这些表达式实际上在做什么。这样一来,宝贵的时间就白白浪费了。除非它没有提供真正的好处,否则我会使用数组索引版本。

标签: c pointers multidimensional-array pointer-arithmetic


【解决方案1】:

如果您需要在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));

【讨论】:

  • 啊!绝妙的解决方案!非常感谢。我也能够省略对int 的类型转换,它仍然像这样(void *)(*(*(a + 1) + 1) + 1));
【解决方案2】:

您可以将指针存储到单独的变量中并将其传递给 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 不会返回任何警告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多