【问题标题】:In C: How to set a pointer to a structure member that is an array?在 C 中:如何设置指向数组结构成员的指针?
【发布时间】:2010-12-07 11:52:45
【问题描述】:

我应该如何编写代码来举例说明恰好是结构成员的数组的特定数组索引?以下代码给我带来了问题。

// main.c

void clean_buffers(void); // prototype

struct DEV_STATUS {
    unsigned char ADDR;
    unsigned char DEV_HAS_DATA;
    unsigned char ETH_HAS_DATA;
    unsigned char DATA[20];
};

struct DEV_STATUS g_cmdQueue[60] = {0};

void main(void) {

    clean_buffers();

    while (1) {
        ;// MCU tasks        
    }
}

void clean_buffers(void) {
    unsigned char theCount = 0;
    byte queIdx;
    for (queIdx = 0; queIdx < 59; queIdx++) {
        struct DEV_STATUS *p_struct;
        unsigned char *p_data;
        p_struct = &g_cmdQueue[queIdx];
        p_data = &p_struct->DATA;
        p_struct->ADDR = 0;
        p_struct->DEV_HAS_DATA = 0;
        p_struct->ETH_HAS_DATA = 0;
        theCount = 0;
        while(*(p_data+theCount) != 0) {
            *(p_data+(theCount++)) = 0;
        }
    }    
} // EOF main.c

我在以下行收到编译器错误“struct/union member expected”

p_data = &p_struct->DATA;

如果要访问例如结构成员 DATA[3] 的特定值,我应该如何编写指针?我很困惑,我认为 p_data = &p_struct->DATA;已定义,我应该可以使用 *(pdata+3) 来获取它,但我想我错过了一些东西。

【问题讨论】:

  • 感谢大家的回复,非常感谢。
  • 错误信息没有意义。你用的是什么编译器?

标签: c pointers structure member dereference


【解决方案1】:

您确定要编译与您在此处发布的代码相同的代码吗?

如果你的编译器在这一行抱怨

p_data = &p_struct->DATA;

如果出现“预期结构/联合成员”消息,您的编译器可能已损坏。

请注意,&amp;p_struct-&gt;DATA 在 C 中是一个完全有效的表达式。这个表达式本身绝对没有问题。

这里的问题是这不是你需要的。 &amp;p_struct-&gt;DATA 返回指向整个数组 'DATA' 的指针,即 unsigned char (*)[20] 类型的指针。您正在尝试将此值分配给unsigned char * 类型的指针。这在 C 中是非法的,因为类型完全不同,但传统上 C 编译器仅以“类型不匹配”警告响应它并执行隐式转换(顺便说一句,这意味着您的原始代码,尽管“脏”,应该仍然按预期工作)。

即使某些编译器决定将此不匹配标记为错误(这很好),它仍然不应该抱怨任何“预期的结构/联合成员”类型的问题。这里不存在这样的问题。

附:正如其他人已经说过的,您真正需要的是p_data = &amp;p_struct-&gt;DATA[0],但这仍然不能解释您的编译器的奇怪行为。难道'DATA'是在'clean_buffers'定义之前某处定义的宏?

于 2009 年 10 月 19 日添加: Nate,在您的代码中,您使用索引 theCount 访问您的数组。由于您无论如何都在使用索引访问,因此甚至没有理由创建您尝试创建的指针。该代码无需任何额外指针即可完美运行,只需直接访问 DATA 字段

theCount = 0;
while (p_struct->DATA[theCount] != 0) {
  p_struct->DATA[theCount++] = 0;

(我可能会在这里使用for 循环)。

如果你真的坚持创建这个指针并且仍然使用索引访问,代码应该如下所示(其他人已经不止一次建议过)

p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
theCount = 0;
while (p_data[theCount] != 0) {
  p_data[theCount++] = 0;

此外,您可以选择更“异国情调”的变体:)

unsigned char (*p_data)[20]; /* <- note: declared differently */
...
p_data = &p_struct->DATA; /* <- note: your original version */
...
theCount = 0;
while ((*p_data)[theCount] != 0) {
  (*p_data)[theCount++] = 0;

但是,返回到 unsigned char *p_data 版本,由于您创建了该指针,因此使用“滑动指针”技术而不是使用索引访问可能更有意义

unsigned char *p_data;
...
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
while (*p_data != 0) {
  *p_data++ = 0;

与往常一样,这完全取决于个人喜好。当然,在您摆脱宏的干扰之前,这些都不会起作用。

【讨论】:

  • &amp;p_struct-&gt;DATA指向字符数组的指针,而不是指向字符的指针。 OP想要后者。
  • @Loadmaster:这正是我在帖子中所说的。你真的读过吗?我的帖子的重点是解释原始发布者他的原始代码的真正含义。并指出错误消息充其量是误导性的。 (至于 OP 想要什么 - 由 OP 决定和告诉。)
  • 不敢相信这被否决了。正是我的想法。现在我不需要再添加答案了:)当然是+1。 (具有讽刺意味的是,接受的答案表明错误的绑定(&amp;p_struct)-&gt;DATA 并且是+4!)
  • @AndreyT,这实际上是我正在寻找的真实信息。感谢您花时间解释一切。您的回答实际上是最有意义的。您实际上是正确的,它是一个宏,用于由我的 main.c 中包含的同事编写的标头中,而不是在另一个模块中(它可以正确编译。)因此,如果隐式转换适用于我的脏代码,我将如何将其重写为“干净”和明确的?
  • @Nate:请看我在回复中添加了什么。
【解决方案2】:

去掉 & in p_data = &amp;p_struct-&gt;DATA;

p_struct 已经是一个指针。然后,使用 p_data[] 访问您的数组。

【讨论】:

  • 谢谢,无论出于何种原因,我从来没有使用 p_data[] 访问数组。我想知道&符号是不是多余的,谢谢您的确认。
  • 您的回答表明绑定是(&amp;p_struct)-&gt;DATA,但事实并非如此。
【解决方案3】:

你应该写的是两件事之一:

p_data = p_struct->DATA; // DATA is the address of the first element.

p_data = &p_struct->DATA[0]; // taking the address of the first element.

【讨论】:

    【解决方案4】:

    只需删除开头的 &,如下所示:

    p_data = p_struct->DATA;
    

    这是数组的特殊语法(记住它们总是作为引用传递),它相当于:

    p_data = &p_struct->DATA[0];
    

    是的,现在你可以使用 *(pdata+3)

    希望对你有帮助。

    【讨论】:

      【解决方案5】:

      哎呀!谢谢AndreyT

      结构 DEV_STATUS *p_struct; 无符号字符 *p_data; p_struct = &g_cmdQueue[queIdx]; p_data = &p_struct->DATA;

      p_struct 是指向struct DEV_STATUS 的指针。
      &amp;p_struct 是指向struct DEV_STATUS 的指针的地址(或指向struct DEV_STATUS 的指针的指针)。

      您可能想将该行更改为

          p_data = p_struct->DATA;
      

      哦...您的 clean_buffers() 函数不会“清理”元素 g_cmdQueue[59]

      而且,因为它是一个全局对象,所以数组 g_cmdQueue 甚至在 main() 的第一条语句执行之前就被初始化为全零。

      【讨论】:

      • 不,你弄错了关联性。 &amp;p_struct-&gt;DATA 代表 &amp;(p_struct-&gt;DATA),而不是 (&amp;p_struct)-&gt;DATA。这里没有指向指针的指针。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 2021-12-17
      • 2018-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多