【问题标题】:Is it possible to 'walk through' the contents of struct?是否可以“遍历”结构的内容?
【发布时间】:2014-12-28 21:22:12
【问题描述】:

我是第一次开始使用 typedef,虽然我很了解结构,但我也没有使用过很多结构。

我创建了一个类型调用Max7219_t,如下所示:

typedef struct {
    uint16_t digit1,
    uint16_t digit2,
    uint16_t digit3,
    uint16_t digit4,
    uint16_t digit5,
    uint16_t digit6
    uint16_t digit7,
    uint16_t digit8,
    uint16_t intensity,
    uint16_t _shutdown,
    uint16_t scanl,
    uint16_t testmode,
    uint16_t decodetype } Max7219_t;

在代码的后面,在我声明了这种类型的变量并添加了值之后,我需要一次传输一个 struct 中的每个字节,最好是在 for 循环中。

除了直接引用每个成员(即*display->digit1,然后是*display->digit2 等)之外,还有其他方法吗?本质上,有没有一种方法可以像使用数组一样枚举每个条目?

我不想只是将整个东西转换成一个数组,因为我几乎肯定会在以后的开发过程中向这个结构和其他结构添加不同的类型。

我觉得我在这里遗漏了一些明显的东西。我在想我可以只增加一个指针,但是因为结构成员的大小不一样,我觉得这不像指向数组的指针那样工作。另外,当迭代 for 循环时,我不确定像 for(q = 0; q != sizeof(Max7219_t); q++) 这样的东西是否也可以工作。

非常感谢任何帮助!

【问题讨论】:

  • because structure members aren't all the same size -- 在你的情况下?
  • 您希望此结构的成员大小为一个字节还是两个? uint16_t 是两个字节。
  • 编译器有时会以不同的方式“打包”结构。
  • 你的类型都是一样的,为什么结构里面没有数组呢?
  • 为什么要转each byte in the struct one at a time?大多数人会一次性移动所有数据。了解这一点可能有助于我们为您提供更好的解决方案。

标签: c loops struct typedef


【解决方案1】:

如果你想:

在后面的代码中,在我声明了一个这种类型的变量并添加了值之后,我需要一次传输一个结构中的每个字节,最好是在一个 for 循环中。

您可以只使用memcpy() 来复制原始数据,或者如果您想访问结构“逐字节”,您可以:

char *ptr = (char*)&Max7219_t_instance;
for(int i = 0; i < sizeof(Max7219_t) ++i){
    // Work with bytes
}

请注意,您不会将任何内容更改为数组,而是强制转换创建指针,该指针会将相同的数据作为不同的类型进行寻址。

如果你想迭代槽结构成员(并且它们不是同一类型......否则使用2501s answer)你将需要反思。有are ways how to employ reflection in C,但我会担心性能影响。

想象一下情况:

??? value = display->digit[x]; // This can be char/short/int/long...

您可以通过在左侧使用 long 来解决此问题,但要使用浮点数和字符串...

哦,好吧...您可以为 MS 编译器解析 .pdb 或为 gcc 解析调试部分(打开 -g),但它与可移植的 C 实现相距甚远。

但是当您需要使用整数类型(或者您可以使用原始二进制数据)时,您可以像这样创建数组:

int Max7219_t_structure_members[] = {sizeof(uint16_t), sizeof(uint16_t) ..., 0 };

这将占用每个结构成员的大小和

sum(Max7219_t_structure_members) == sizeof(Max7219_t)

为了论证,我们假设您只需要使用最大为 sizeof(long) 字节的类型。

int offset = 0;
for(int i; Max7219_t_structure_members[i]; ++i){
    long tmp = 0;
    // This line will work only on little-endian machines
    memcpy(&tmp, ((char*)insntance)+offset, Max7219_t_structure_members[i])

    // Do your work

    offset += Max7219_t_structure_members[i];
}

但是您必须手动维护该结构。我不知道有任何宏(至少在 gcc 中)可以帮助您实现自动化版本。

【讨论】:

  • 这是另一个有趣的答案,而且肯定会奏效,尤其是在需要确定性行为的情况下。很抱歉我的措辞含糊不清,我的意思是通过 SPI 转移。
【解决方案2】:

由于您的类型相同,请创建这些类型的数组:

typedef struct
{
     uint16_t mode[13] ;

}  Max7219_t ;

您像遍历任何其他数组一样遍历它。

 Max7219_t var = { 0 } ;

 for( size_t i = 0 ; i < 13 ; i++ )
 { 
     var.mode[i] = 12345 ;
 }

此方法不允许您为元素使用名称:digit1、digit2 ...

您可以通过使用枚举来获取它们,这些枚举对应于数组中的正确元素。

enum
{
    digit1 = 0 ,
    digit2 = 1 ,
    digit3 = 2 ,
    //... and so on
} ;

【讨论】:

    【解决方案3】:

    联合的用例:

    union variable {
        Max7219_t yourStructure;
        uint16_t array[13];
    );
    

    【讨论】:

    • 我不是反对者,但如果您像这样声明array,这将是一个更可行的解决方案:char array[sizeof(Max7219_t)];
    • 我不这么认为。 TO想要以uint16_t的数组而不是字符数组的形式访问结构数据。
    • 我们对他的问题有不同的解释。不完全清楚。
    • 我正在考虑使用联合,但在这种情况下最终不会起作用。
    【解决方案4】:

    由于结构中的所有元素大小相同,理论上您可以声明一个指向 uint16_t 的指针,该指针指向结构中的第一个元素,如下所示:

    Max7219_t my_structure;
    uint16_t *p = (uint16_t *)&my_structure;
    for (int i = 0; i < ELEMENTS_IN_STRUCTURE; i++, p++) {
        *p = some_value;
    }
    

    但是,我完全不建议这样做,因为如果您将其他变量类型添加到结构中,它将无法工作,并且完全违背了结构和类型的目的。

    我会做的是编写一个根据需要填充值的函数。

    void init_max_77219(Max7219_t *my_structure) {
        my_strcture->digit1 = ...;
    }
    

    然后在需要初始化结构时调用它。

    对于这种特殊情况(结构体充当uint16_t 的包),您可以根据需要坚持使用数组,然后将不同类型的变量存储在其他地方。

    【讨论】:

    • 这是我最初的想法,但它不适用于我的特定问题。不过感谢您的帮助!
    【解决方案5】:

    如果您需要访问“隐藏”在结构后面的原始内存,有两种方法:

    • memcpy()
    • 带有类型转换指针的for循环

    最后一种方法似乎最接近你想要的,所以可能是这样的:

    Max7219_t yourStructure;
    // ...
    
    const uint8_t* const pointer = (const uint8_t*)&yourStructure;
    for (size_t i = 0; i < sizeof(yourStructure); ++i)
    {
        uint8_t byte = pointer[i];
        ...
    }
    

    您的问题并不完全清楚...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-27
      • 2011-06-14
      • 2015-03-10
      • 2022-01-07
      相关资源
      最近更新 更多