Dhan
Dhan

Reputation: 19

C-Access Members of Struct using index

I have a Structure defined which looks like this

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;
};

I want to read the member of structure using index like

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

Is this possible by using any tricks?

Upvotes: 0

Views: 109

Answers (2)

Bwebb
Bwebb

Reputation: 685

Any pointer arithmetic youre using will increase by the sizeof the stuct, so you would need to know how many bytes you need, and cast it to unsigned char * before trying to index into it. As the comments mention this is a bad idea, bad practice, not portable from 32/64 bit pointers, horrible to read/etc. That being said it can be done with a platform specific implementation

#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;
}

Compiled and tested on codechef.com/ide has the following output:

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

As some of the other comments suggest, if your struct is not packed down to the byte with #pramga pack you will have to account for padding. Use the conventional ways to printf the addresses then make sure you "index variables" point to the same address.

Actually, dont ever do this at all unless your just curious. Interesting question though so ill give it a thumbs up, even though its useless practically, from a theoretical answer this one was more interesting than some others ive tried to get rep from.

Upvotes: 0

Eric Postpischil
Eric Postpischil

Reputation: 222302

The goal you have requested is a Bad Idea, and there is almost certainly a better way of achieving the actual goal that motivated this notion.

That said, one way of implementing this that is less bad than some others is to use an array of offsets as paddy suggested:

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));
}

Note that the address is returned only as a void * because there are different types in the structure. You still need some mechanism to handle the different types.

Upvotes: 2

Related Questions