【问题标题】:Get the index of an element declared in a struct获取结构中声明的元素的索引
【发布时间】:2021-07-22 09:07:46
【问题描述】:

我想将我的结构的每个元素(或其他东西,可能无法使用结构)与递增索引相关联,有点像枚举,但与值字段相关联。 假设我有这个数据结构:

typedef struct
{
    int8_t value_at_index0; // start with index 0 for this field
    int8_t value_at_index1; // then index = 1, etc
    int8_t value_at_index2;
    int8_t value_at_index3;
    int8_t value_at_index4;
} data;

我想获取一个字段的索引,索引应该反映该字段在结构中声明的位置。

编辑:我的问题是我想在外部存储器中写入值,但我不想确定哪个索引是值。例如我想这样做:write(index.value_at_index2, data.value_at_index2)

谢谢

【问题讨论】:

  • associate each element of my struct (or something else, may not be possible with a struct) with an incrementing index 有什么用?您将如何使用该索引? For now I'm simply declaring 请发布您的代码。你为什么这样做?为什么要“在 for 循环中声明两个相同的结构”,而您“增加索引”是为了什么?
  • @KamilCuk:用于在内存中写入数据。我有一个结构来映射内存的值
  • 只需将整个结构写入内存memcpy(memory, &data, sizeof(data))
  • 这听起来很像XY Problem。你实际上想要达到什么目的?
  • 如果我只想将结构的一个元素写入我的记忆?例如write(index, data.value_at_index2),如何获取索引(假设我不知道)?

标签: c struct enums


【解决方案1】:

好吧,我假设你的代码写得不好并且不想修复它或者它是一个非常具体的问题

虽然我只会使用一个数组或为其分配一些内存,但我还没有阅读手册,但我记得一年前结构总是写成一个块(即它们不像内存分配那样是碎片化的)虽然这不是使用这样的结构的正确行为,但我做了一个测试并且它有效 使用__attribute__((packed, aligned(1))),这使得填充为1,意味着不会添加空格字节,也就是说,如果你有一个单字节元素,它不会再添加3个空格来填补空白。

这并不意味着它将所有内容都缩短为一个,并且一旦您考虑到不同大小的元素,它就会停止工作,因为当它通过 4 字节整数时添加一个会导致意外行为


    typedef struct __attribute__((packed, aligned(1))) //like so
    {
        int8_t value_at_index0; // start with index 0 for this field
        int8_t value_at_index1; // then index = 1, etc
        int8_t value_at_index2;
        int8_t value_at_index3;
        int8_t value_at_index4;
    } data;
    
    int main(int argc, char **argv){
        data data;
        int8_t *hey=NULL;
        data.value_at_index0=5;
        data.value_at_index1=3;
        data.value_at_index2=2;
        data.value_at_index3=5;
        data.value_at_index4=10; 
        size_t i;
        hey = &data;
        for (i = 0; i < 5; i++){
            
            printf("hey its working %d", *hey);
            hey+=1;
        }
        
        
        //letsee(5, data);
        return 0;
    }

现在这不是正确的行为,从你的问题表面上看,我只是建议你坚持内存分配,因为它允许动态大小,即使你想要静态大小,你也可以只使用数组。 如果您想在最新的 C 编译器中获得上述更粗略的版本,可以使用一些技巧使其动态化。虽然我会告诉你,你会有一堆内存泄漏、核心转储和意外行为

TL;DR 这是不正确的行为,我只是发布这个以防您无法更改代码和你必须使用结构

现在是干净的版本,我在问题中读到,假设该结构是基本的,您将编写一个结构,并且您只想在其中编写每个静态元素,您可以轻松做到


    FILE *fp;
    if ((fp = fopen("lets.txt", "w")) == NULL){
        return 1;
    }
    
    fwrite(&data, sizeof(data), 1, fp);
    if (fclose(fp) != 0){
        return 1; 
    }

因为当你在第一个参数中放置一个结构并提供它的大小时,它只会写入结构内的每个元素,这也适用于指针,尽管你必须在大小参数中指定每个元素的大小以及下一个参数中的元素数量。 同样,这是假设您的所有元素都定义明确且是静态的,因为结构有很多标志

【讨论】:

    【解决方案2】:

    您应该考虑为此目的使用数组/指针。要完成这项工作,您需要确保所有值都是相同类型并临时删除该结构的内存填充。以下代码说明了它是如何完成的。

    /*Remove struct padding*/
    #pragma pack(push, 1)
    typedef struct
    {
       int8_t a;
       int8_t b;
       int8_t c;
       int8_t d;
    } data;
    /*Recover struct padding, some structs from other libraries malfunction from not using struct pudding.*/
    #pragma pack(pop)
    
    int main()
    {
       /*Define a clean data structure*/
       data tmp = { 0x00, 0x00, 0x00, 0x00 };
    
       ((int8_t *)&tmp)[0] = 0x01; /*data.a = 0x01*/
       ((int8_t *)&tmp)[1] = 0x03; /*data.b = 0x03*/
       ((int8_t *)&tmp)[2] = 0x05; /*data.c = 0x05*/
       ((int8_t *)&tmp)[3] = 0x07; /*data.d = 0x07*/
    
       return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-16
      • 2013-04-01
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 2013-12-03
      • 1970-01-01
      • 2015-08-30
      相关资源
      最近更新 更多