By CIsForCookies


2018-04-16 13:02:22 8 Comments

I have a list of variables char [][20] ls = {"var_1", "var_2", ... , ""}

which are the names of the fields of a struct struct {char var1[10], ...} my_struct;

The variables inside the struct are all char[] with changing lengths. The list itself is const and should not change mid-run-time.

I want to access those variables in a loop in a somewhat generic way. Instead of calling myfunc(my_struct.var1); myfunc(my_struct.var2); and so on, I would much rather have:

for (char * p = ls[0]; *p; p += sizeof(ls[0]))
{
  myfunc(my_struct.{some magic that would put var_1 / var_2 here});
}

But I guess this is impossible due to fact that the loop is executed in run-time, and the variable name needs to be available in compile-time.

Am I correct or is there something that can be done here? (not have to be this way, just wants to know if I can pack this routine into a nice loop)

2 comments

@Lundin 2018-04-16 13:53:04

Assuming you have something like

const char* ls[] = {"var_1", "var_2", ""};

where this list is not tightly-coupled to the struct data (if so you can use the answer by dbush), but is a separate item for whatever reason.

Then the slightly hacky, but well-defined version would be to use look-up tables. Create two lookup tables, one with strings, one with offsets:

#include <stddef.h>

typedef struct
{
  int var_1;
  int var_2;
} my_struct_t;

static const char* VAR_STRINGS[] =
{
  "var_1",
  "var_2",
  ""
};

static const size_t VAR_OFFSET[] =
{
  offsetof(my_struct_t, var_1),
  offsetof(my_struct_t, var_2),
};

Then do something like index = search_in_VAR_STRINGS_for(ls[i]); to get an index. (Loop through all items, or use binary search etc). The following code is then actually legal and well-defined:

unsigned char* ptr = (unsigned char*)&my_struct;
ptr += VAR_OFFSET[index];
int var_1 = *(int*)ptr;

This takes padding in account and the pointer arithmetic is guaranteed to be OK by C11 6.3.2.3/7:

When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

And since what's really stored at that address (effective type) is indeed an int, the variable access is guaranteed to be OK by C11 6.5/7 ("strict aliasing"):

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
— a type compatible with the effective type of the object,

But various error handling obviously needs to be in place to check that something doesn't go out of bounds.

@dbush 2018-04-16 13:07:17

Since all members are arrays of the same type, you can create an array of addresses to each member and loop through that:

char *my_struct_addrs[] = { my_struct.var1, my_struct.var2, ... };
int i;
for (i=0; i < sizeof(my_struct_addrs) / sizeof(my_struct_addrs[0]); i++) {
    myfunc(my_struct_addrs[i]);
}

Since the size of each of these arrays is different however, you'll need to take care not to pass the bounds of each one. You can address this by keeping track of the size of each field and passing that to the function as well:

struct addr_list {
    char *addr;
    int len;
};

struct addr_list my_struct_addrs[] = { 
    { my_struct.var1, sizeof(my_struct.var1) },
    { my_struct.var2, sizeof(my_struct.var2) },
    ...
};

int i;
for (i=0; i < sizeof(my_struct_addrs) / sizeof(my_struct_addrs[0]); i++) {
    myfunc(my_struct_addrs[i].addr, my_struct_addrs[i].len);
}

@CIsForCookies 2018-04-16 13:08:52

That's cool. I can add a offsets array to take care of that

@P__J__ 2018-04-16 13:13:11

@dbush - searching the array of structures is not the language feature as OP requested

@CIsForCookies 2018-04-16 13:14:20

@PeterJ_01 However it does help me to achieve what I need.

@Stargateur 2018-04-16 14:16:15

Note: that unless a very good reason len should be a size_t and i declare INSIDE the for loop

Related Questions

Sponsored Content

22 Answered Questions

[SOLVED] How can I get the list of files in a directory using C or C++?

  • 2009-03-04 19:35:58
  • samoz
  • 664155 View
  • 447 Score
  • 22 Answer
  • Tags:   c++ c file directory

14 Answered Questions

[SOLVED] How do I use extern to share variables between source files?

0 Answered Questions

Saving variables to arrays that change their name over a loop

  • 2016-11-27 14:31:37
  • user7216373
  • 48 View
  • 0 Score
  • 0 Answer
  • Tags:   c arrays vector

2 Answered Questions

[SOLVED] Dynamic variables in C

  • 2016-04-30 03:04:54
  • user5737301
  • 120 View
  • 0 Score
  • 2 Answer
  • Tags:   c

4 Answered Questions

[SOLVED] How do I achieve the theoretical maximum of 4 FLOPs per cycle?

1 Answered Questions

How to define const variable on RAM?

1 Answered Questions

0 Answered Questions

Data in linked list being overwritten

  • 2015-04-12 00:15:58
  • Joseph Seung Jae Dollar
  • 110 View
  • 0 Score
  • 0 Answer
  • Tags:   c linked-list

2 Answered Questions

[SOLVED] How to create an array of const structs

  • 2014-04-15 01:38:46
  • Bob Broadley
  • 3064 View
  • 2 Score
  • 2 Answer
  • Tags:   c arrays struct

2 Answered Questions

[SOLVED] Is there a bit-equivalent of sizeof() in C?

  • 2010-07-23 15:32:55
  • eruciform
  • 12758 View
  • 22 Score
  • 2 Answer
  • Tags:   c sizeof bit-fields

Sponsored Content