【问题标题】:Can I access a union in my source.c from main.c in PIC C18?我可以从 PIC C18 中的 main.c 访问我的 source.c 中的联合吗?
【发布时间】:2018-12-05 09:10:46
【问题描述】:

我处于一个包含多个元素的匿名结构的位置。为了通过索引访问它们,我将它们放在一个联合中,如下所示:

union
{
    struct
    {
        unsigned char COMMAND;      //STRUCT_ARRAY[0]
        unsigned char ADDR_H;       //STRUCT_ARRAY[1]
        unsigned char ADDR_M;       //STRUCT_ARRAY[2]
        unsigned char ADDR_L;       //STRUCT_ARRAY[3]
        unsigned char DATA;         //STRUCT_ARRAY[4]
        unsigned char CHECKSUM;     //STRUCT_ARRAY[5]
    };
    unsigned char STRUCT_ARRAY[6];
    //all of the struct members can be accessed from STRUCT_ARRAY by index
}MY_UNION;

此联合当前位于文件 source.c 中。我需要从main.c 访问它。我有一个两个文件都包含的标题,我们称之为header.h

如何在 main.c 中读取 ADDR_HADDR_M 的值,同时定期从 source.c 修改它?

代码有点像这样:

source.c:

#include "header.h"

union
{
    struct
    {
        unsigned char COMMAND;      //STRUCT_ARRAY[0]
        unsigned char ADDR_H;       //STRUCT_ARRAY[1]
        unsigned char ADDR_M;       //STRUCT_ARRAY[2]
        unsigned char ADDR_L;       //STRUCT_ARRAY[3]
        unsigned char DATA;         //STRUCT_ARRAY[4]
        unsigned char CHECKSUM;     //STRUCT_ARRAY[5]
    };
    unsigned char STRUCT_ARRAY[6];
    //all of the struct members can be accessed from STRUCT_ARRAY by index
}MY_UNION;

void modify(void)
{
    MY_UNION.ADDR_H = somevalue;
    MY_UNION.ADDR_M = somevalue;
    MY_UNION.ADDR_L = somevalue;
}

在 main.c 中:

#include "header.h"

void main(void)
{
    modify();
    print(MY_UNION.ADDR_H);    //custom function to print values to a screen
    print(MY_UNION.ADDR_M);
    print(MY_UNION.ADDR_L);
}

【问题讨论】:

  • 外部关键字?

标签: c unions extern


【解决方案1】:

基本程序设计:

  • 切勿在头文件中声明变量。
  • 切勿对extern 使用意大利面条式编程。
  • 不要在处理协议的翻译单元之外直接公开诸如此协议结构之类的内部结构。您需要在两者之间有一个抽象层。

快速而肮脏的解决方案:

  • 将h文件中的union定义改为typedef:

    typedef union 
    {
        struct
        {
            unsigned char COMMAND;      //STRUCT_ARRAY[0]
            unsigned char ADDR_H;       //STRUCT_ARRAY[1]
            unsigned char ADDR_M;       //STRUCT_ARRAY[2]
            unsigned char ADDR_L;       //STRUCT_ARRAY[3]
            unsigned char DATA;         //STRUCT_ARRAY[4]
            unsigned char CHECKSUM;     //STRUCT_ARRAY[5]
        };
        unsigned char STRUCT_ARRAY[6];
        //all of the struct members can be accessed from STRUCT_ARRAY by index
    } MY_UNION;
    
  • 在.c文件中本地声明实际变量:static MY_UNION my_union;

  • 使用 setter/getter 访问变量,例如:

    uint8_t get_address_h (void)
    {
      return my_union.ADDR_H;
    }
    
    void set_address_h (uint8_t addr_h)
    {
      my_union.ADDR_H = addr_h;
    }
    

正确的解决方案:

在一个适当的程序中,你应该完全隐藏这个协议的内部,对其他文件,包括 typedef 联合。

除了协议转换器之外没有人可以访问这个联合。您将拥有 set_addressset_data 等函数,调用者无需了解协议内部即可知道这些函数。

【讨论】:

  • 在 OP 的代码中 MY_UNION 是变量名。保持相同的约定会更容易。
  • @RishikeshRaje 他们不应该在标头中声明变量,因此无法保留原始代码。
  • 我没有在标题中声明任何变量,这就是为什么我没有在我的问题中为header.h 提供任何代码。我在这里写的代码是否暗示了这一点?
  • @Jǝssǝ union{ ... }MY_UNION; 声明了一个名为 MY_UNION 的变量。它如何在没有联合标记或 typedef 的情况下进行编译,您将不得不询问出色的 PIC 编译器。
  • 我接受了另一个答案,因为它看起来合乎逻辑,有效并且看起来“正确”。您的回答提供了更好的背景和建议。 (我并不是说你的回答不好@RishikeshRaje)。但是,我不喜欢在接受后删除它,所以我只是投了赞成票。我为我太仓促道歉。
【解决方案2】:

最简单的方法是 typedef the union

在 header.h 中

typedef union
{
    struct
    {
        ...
    };
    unsigned char STRUCT_ARRAY[6];
}MyUnionType;

extern MyUnionType MY_UNION;

然后在source.c中定义变量

MyUnionType MY_UNION;

这个变量现在可以在任何源文件中使用。 (main.c 等)

【讨论】:

  • typedef从不必需的,不是这里的相关部分,而是一个红鲱鱼。
  • @toohonestforthissite - 在任何情况下都需要在头文件中声明联合以允许它是外部的。 typedef 或联合标签是两种方式。
  • @RishikeshRaje 没有必要使用extern,这只是一个糟糕设计的超强迹象。
  • @Lundin - 如果你在谈论全局变量,我完全同意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
  • 2018-01-25
  • 1970-01-01
相关资源
最近更新 更多