使用索引的Struct C-Access成员

时间:2018-11-28 04:25:46

标签: c

我定义了一个看起来像这样的结构

struct tindex
{
  char* fcode;
  char* fdesc;
  int fstartidx;
  int fsize;
  char* ftype;
  char* precision;
  char* fcons;
  char* notnull;
  char* ronly;
  char* wdth;
  char* res2;
  char* cel;
  char* flr;
};

我想使用像这样的索引读取结构的成员

struct tindex *idx= (struct tindex*)malloc(sizeof(struct tindex));
sscanf(cur,"%s",idx[0]); //Access first member of struct

使用任何技巧是否有可能?

2 个答案:

答案 0 :(得分:2)

您所要求的目标是一个坏主意,几乎可以肯定有一种更好的方法来实现激发该概念的实际目标。

也就是说,一种实现这种效果的方法比其他方法要差的一种方法是使用paddy建议的偏移量数组:

struct tindex
{
    char* fcode;
    char* fdesc;
    int fstartidx;
    int fsize;
    char* ftype;
    char* precision;
    char* fcons;
    char* notnull;
    char* ronly;
    char* wdth;
    char* res2;
    char* cel;
    char* flr;
};


#include <stddef.h>


void *LookupField(struct tindex *p, int index)
{
    static const size_t Offsets[] =
    {
        offsetof(struct tindex, fcode),
        offsetof(struct tindex, fdesc),
        offsetof(struct tindex, fstartidx),
        offsetof(struct tindex, fsize),
        offsetof(struct tindex, ftype),
        offsetof(struct tindex, precision),
        offsetof(struct tindex, fcons),
        offsetof(struct tindex, notnull),
        offsetof(struct tindex, ronly),
        offsetof(struct tindex, wdth),
        offsetof(struct tindex, res2),
        offsetof(struct tindex, cel),
        offsetof(struct tindex, flr),
    };

    return (char *) p + Offsets[index];
}


#include <stdio.h>


int main(void)
{
    struct tindex t;
    printf("%p = %p.\n", (void *) &t.fcode, LookupField(&t, 0));
    printf("%p = %p.\n", (void *) &t.fcons, LookupField(&t, 6));
    printf("%p = %p.\n", (void *) &t.flr, LookupField(&t, 12));
}

请注意,由于结构中存在不同的类型,因此地址仅作为void *返回。您仍然需要某种机制来处理不同的类型。

答案 1 :(得分:0)

您使用的任何指针算术运算都会增加结构体的大小,因此您需要知道需要多少字节,然后将其转换为unsigned char *,然后再尝试对其进行索引。就像评论中提到的那样,这是一个坏主意,不好的做法,不能从32/64位指针移植,很难读/等。话虽如此,可以通过特定于平台的实现来完成

#include <stdio.h>
#include <stdlib.h>

struct tindex 
{
  char* fcode;
  char* fdesc;
  int fstartidx;
  int fsize;
  char* ftype;
  char* precision;
  char* fcons;
  char* notnull;
  char* ronly;
  char* wdth;
  char* res2;
  char* cel;
  char* flr;
};

int main(void) {
  struct tindex *idx= (struct tindex*)malloc(sizeof(struct tindex));
  idx->fstartidx = 42;

  //a more intereting example, base_address[1] will always increment by 1 byte (for example) when you try to implememtn other members
  unsigned char * base_address = (unsigned char *)idx;
  int * why_do_this = (int *)(base_address + 2*sizeof(char*));
  *why_do_this = 43;

  printf("First some sizes: sizeof struct=%zu \t sizeof char *=%zu\t  2*sizeof(char*)=0x%04x\n", sizeof(struct tindex), sizeof(char*), 2*sizeof(char*));
  printf("Starting address %p, new offset %p, delta 0x%04x should be 2* sizeof char *\n", idx, why_do_this, (int)why_do_this - (int)idx);
  printf("The intfstart index value should be %d which actually is now %d", *why_do_this, idx->fstartidx); //the intfstart index
  return 0;
}

在codechef.com/ide上经过编译和测试的输出如下:

First some sizes: sizeof struct=96   sizeof char *=8     2*sizeof(char*)=0x0010
Starting address 0x5573c0327010, new offset 0x5573c0327020, delta 0x0010 should be 2* sizeof char *
The intfstart index value should be 43 which actually is now 43

正如其他一些注释所建议的那样,如果未使用#pramga pack将结构压缩为字节,则必须考虑填充。使用常规方法来打印地址,然后确保“索引变量”指向相同的地址。

实际上,除非您只是好奇,否则根本不要这样做。有趣的问题虽然不那么实用,但还是给了我一个赞许,尽管从理论上来说它毫无用处,但从理论上来说,这个问题比其他一些我试图从中获得代表的问题更有趣。

相关问题