tags:

views:

191

answers:

5

Hi,

I am trying to declare a struct that is dependent upon another struct. I want to use sizeof to be safe/pedantic.

typedef struct _parent
{
  float calc ;
  char text[255] ;
  int used ;
} parent_t ;

Now I want to declare a struct child_t that has the same size as parent_t.text.

How can I do this? (Pseudo-code below.)

typedef struct _child
{
  char flag ;
  char text[sizeof(parent_t.text)] ;
  int used ;
} child_t ;

I tried a few different ways with parent_t and struct _parent, but my compiler will not accept.

As a trick, this seems to work:

parent_t* dummy ;
typedef struct _child
{
  char flag ;
  char text[sizeof(dummy->text)] ;
  int used ;
} child_t ;

Is it possible to declare child_t without the use of dummy?

Thanks.

+7  A: 

Use a preprocessor directive, i.e. #define:

#define TEXT_LEN 255

typedef struct _parent
{
  float calc ;
  char text[TEXT_LEN] ;
  int used ;
} parent_t ;

typedef struct _child
{
  char flag ;
  char text[TEXT_LEN] ;
  int used ;
} child_t ;
dave mankoff
simplest. don't make it complicated unless necessary.
Nyan
Agree with Nyan. The other solutions work, but don't accomplish anything different. If you want to be more explicit, call it PARENT_TEXT_LEN or something equally descriptive. You can then also use it in conditionals throughout your code to prevent buffer length errors and it will be doing simple integer comparisons.
dave mankoff
i think the advantage of the sizeof solution is that you don't need access to the parent struct, if it is defined in a library or somewhere else.
@evilclown: but you do: "char text[member_size(Parent, text)];" You need to reference the "Parent".
dave mankoff
@dave, i don't think you understood me. suppose the parent struct is `drand48_data` (defined in stdlib.h) and you want the sizeof `__x`. you cannot `#define X_LEN 3` and change the stdlib.h, using `member_size` is superior when you don't have access to the source of the parent struct, which seems like a reasonable situation.
+3  A: 

You can use a preprocessor directive for size as:

#define TEXT_MAX_SIZE 255

and use it in both parent and child.

codaddict
+8  A: 

I am not on my development machine right now, but I think you can do one of the following:

sizeof(((parent_t *)0)->text)

sizeof(((parent_t){0}).text)


Edit: I like the member_size macro Joey suggested using this technique, I think I would use that.

Brandon Horsley
Should be `parent_t *`, not `_parent *`.
mkarasek
C99 feature!!!.
Nyan
The second form is very nice (and conceptually clean in that it does not involve null pointers), but you should mention that it's not possible in pre-C99 compilers.
R..
+12  A: 

Although defining the buffer size with a #define is one idiomatic way to do it, another would be to use a macro like this:

#define member_size(type, member) sizeof(((type *)0)->member)

and use it like this:

typedef struct
{
    float calc;
    char text[255];
    int used;
} Parent;

typedef struct
{
    char flag;
    char text[member_size(Parent, text)];
    int used;
} Child;

I'm actually a bit surprised that sizeof((type *)0)->member) is even allowed as a constant expression. Cool stuff.

Joey Adams
Wow, I didn't know sizeof((type *)0)->member) works. Am not on my dev machine now, but does this work for all the compilers? Thanks for that Joey.
Gangadhar
@Gangadhar: Yes, this works for all compilers. The operand of `sizeof` is not evaluated, so there is no issue with dereferencing the null pointer (because it isn't actually dereferenced).
James McNellis
Wow! Many kudos for this wonderful gem :-)
jweyrich
wonderful? its plain C89, see implementation of "offsetof" in <stddef.h> or the same implementation http://www.eetimes.com/design/other/4024941/Learn-a-new-trick-with-the-offsetof--macro
@gordongekko: Thank you. Still a gem and wonderful for me.
jweyrich
+3  A: 

Another possibility would be to define a type. The fact that you want to ensure the same size for the two fields is an indicator that you have the same semantics for them, I think.

typedef char description[255];

and then have a field

description text;

in both of your types.

Jens Gustedt