【问题标题】:Pointer to typedef of an array指向数组的 typedef 的指针
【发布时间】:2017-12-29 14:15:12
【问题描述】:

我正在尝试做以下事情:

#include <stdio.h>

typedef unsigned char Set[128];

Set A;  //Global variable

void main()
{
    A[0] = 1;
    A[1] = 2;
    A[2] = 3;
    printf("%x, %x, %x\n", A, &A, &A[0]);
    printf("%u, %u, %u\n", A[0], A[1], A[2]);
    Set *p;
    p = A;  //Same result with:  p = &A;
    printf("%x, %x, %x\n", p, &p, &p[0]);
    printf("%u, %u, %u\n", p[0], p[1], p[2]);
}

第一次和第三次打印都很好——我可以看到两个变量的地址,对于“p”,它指向的地址。 我希望'p'指向'A',这样我就可以通过'p'访问'A'数组中的值,但它不起作用-第四次打印的值不是第二,它不打印数组的值。 如何创建指向“设置”变量类型的指针?

【问题讨论】:

  • 你为什么要创建一个令你的例子复杂化的 typedef ?你所有的 printf 调用都是未定义的行为。
  • p = A 无效。假设警告级别足够高,编译器会向您提及它。认真对待编译器的警告。

标签: c arrays pointers types typedef


【解决方案1】:

您为提供的参数类型使用了许多错误/不匹配的格式说明符。这会导致undefined behavior

请记住,对于指针类型,您必须使用 %p 格式说明符,并且如果指针不是指向 char 类型的指针,则必须将参数强制转换为 void *


关于上述关于强制转换要求的声明,请参阅第 §6.2.5/P28 章,

指向 void 的指针应具有与 指向字符类型的指针。 [....]

和脚注 48,

相同的表示和对齐要求意味着可互换性 函数的参数、函数的返回值以及联合的成员。


话虽如此,请始终注意类型!

在您的代码中,

  • A 的类型为 unsigned char [128](数组),
  • p 的类型为 unsigned char (*) [128]

因此,p = A; 不是有效语句,因为类型不兼容。您必须使用A 的地址才能使声明有效,例如

 p = &A;  // now the types are compatible

【讨论】:

  • @alk 不,我有一些支持我的东西,实际上...... :)
  • @alk 啊,明白了。 §6.2.5/P28 ..“指向 void 的指针应具有与指向字符类型的指针相同的表示和对齐要求。”
  • 你好,我又是马里奥……好吧。所以我想出了新/旧信息stackoverflow.com/a/24304460/7076153(在“官方解释”部分阅读答案的结尾),似乎发送char *而不投到void *printf()%p不是严格符合。由于脚注具有误导性,因此只是一个建议。
【解决方案2】:

那是因为p 的指针类型与a 的类型不同。在这里,当您尝试使用p[1] 时,您基本上是在尝试访问一些您无权访问的内存。 (当您访问 p[1] 等时,您有未定义的行为)。而且由于类型不匹配,您还将在printf 本身中遇到未定义的行为。

相反,您可以通过(现在您将获得所需的数组元素)。

printf("%u, %u, %u\n", (*p)[0], (*p)[1], (*p)[2]);

还要键入 ponters 使用 %p 格式说明符。 (将其投射到void*)。

printf("%p, %p, %p\n", (void*)A, (void*)&A, (void*)&A[0]);

如何编译代码?

还可以尝试在启用所有警告的情况下编译您的代码。 gcc -Wall -Werror progname.c.

编译器报错!

还有p=A 编译器抱怨它。因为您将unsigned char* 分配给unsigned char(*)[128]

 error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
     p = A;  //Same result with:  p = &A;
       ^

error: format ‘%x’ expects argument of type ‘unsigned int’, but argument 4 has type ‘unsigned char (*)[128]’ [-Werror=format=]
     printf("%x, %x, %x\n", p, &p, &p[0]);
                      ^

如何让这些警告消失?

p=&A;

这将执行正确的分配。并使用答案中提到的正确格式说明符。

unsigned char* 是怎么出现的?

在这种情况下,数组衰减为指针 - 它衰减为指向第一个元素的指针。第一个元素的类型是unsigned char - 指向它的指针是unsigned char*。原来是这样的……

【讨论】:

    【解决方案3】:

    p 是指向unsigned char [128] 类型的指针,这意味着它是unsigned char (*)[128] 类型,而A 的类型在衰减后是unsigned char *。两者都是不兼容的类型。你需要

    p = &A; 
    

    printf("%p, %p, %p\n", (void *)A, (void *)&A, (void *)&A[0]);
    printf("%u, %u, %u\n", A[0], A[1], A[2]);
    Set *p;
    p = &A; // Assign address of A which is of type unsigned char (*)[128]
    printf("%p, %p, %p\n", (void *)p[0], (void *)p, (void *)&p[0]);
    printf("%u, %u, %u\n", p[0][0], p[0][1], p[0][2]);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-03
      • 2011-03-04
      • 1970-01-01
      • 2021-02-07
      相关资源
      最近更新 更多