0

As introduced here, the va_list type is implemented as follows

typedef struct {
   unsigned int gp_offset;
   unsigned int fp_offset;
   void *overflow_arg_area;
   void *reg_save_area;
} va_list[1];

Can I directly modify the structure members of a va_list variable?

va_list ap; 
ap[0].gp_offset = 123;   // I want something like this
ap->gp_offset = 123;     // but none of these compile

When I try running this, I get these errors respectively

error: request for member 'gp_offset' in 'ap[0]', which is of non-class type '__va_list_tag'

error: request for member 'gp_offset' in '*(__va_list_tag*)(& ap)', which is of non-class type '__va_list_tag'

Why am I asking? I'm working with a large database, and I saw a somewhat hacky way to modify a va_list variable as below. I wonder if this can be done without all this hassle.

va_list ap;
// Mimic GCC data structure
typedef struct {
   unsigned int gp_offset;
   unsigned int fp_offset;
   void *overflow_arg_area;
   void *reg_save_area;
}va_list2[1];

char* ap2 = (char*)≈         // same address as ap
va_list2* ap3 = (va_list2*)ap2; // same address as ap
(*a3)->gp_offset = 123;         // Now this is allowed!
Community
  • 1
  • 1
kgf3JfUtW
  • 13,702
  • 10
  • 57
  • 80
  • 6
    Just don't do it. Whatn an `va_list` is is an "implementation detail", and using it except with the `va_*` macros and functions is not portable, and definitely not defined behavior in any way. – Some programmer dude Dec 07 '16 at 16:05
  • 2
    What problem are you trying to solve? – Pete Becker Dec 07 '16 at 16:08
  • Hi @PeteBecker, regarding what exactly this code is meant to achieve, I don't really know :-( The developer left the company years ago, leaving barely any comments/explanations, although the code has been working perfectly so far. Regarding this question, I just wanted to know if I can make this very unsafe code less unsafe (look at those C style casts)... – kgf3JfUtW Dec 07 '16 at 16:12
  • 2
    The unsafe part is messing with the internals of `va_list`. The casts are fine. – melpomene Dec 07 '16 at 16:14
  • @melpomene Now this might be a completely different question, but why is it necessary to cast `&ap` to `char*` first, before casting to `va_list2*`? – kgf3JfUtW Dec 07 '16 at 16:18
  • 1
    Because [*type punning*](https://en.wikipedia.org/wiki/Type_punning) (pretending one type is another type) breaks [*the strict aliasing rule*](http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule) if not done though pointers to `char`. – Some programmer dude Dec 07 '16 at 16:21
  • Re: " I don't really know :-(" -- then, unfortunately, you're stuck. Personally, I wouldn't touch it. If you change it you're responsible for any harm the changes do. This is a case where "if it ain't broke, don't fix it". – Pete Becker Dec 07 '16 at 16:27
  • @Someprogrammerdude Thank you very much for pointing these out and including the links. *Type punning* and *the strict aliasing rule* are both new concepts for me. I'll certainly read up on them. – kgf3JfUtW Dec 07 '16 at 16:31

1 Answers1

1

That answer was for a C question, but even that answer is technically incorrect.

What a va_list is, is undefined in both languages. You might be able to do something compiler/library/ABI specific, but my advice is to find another way to do whatever it is you are trying to do.

IanM_Matrix1
  • 1,564
  • 10
  • 8