typdef enum {
elem_type_string;
elem_type_int;
elem_type_double;
} elem_type;
typedef struct {
char string_data[100];
int num_data;
double float_data;
} foo;
typedef struct {
char* element_name;
size_t element_size;
size_t element_offset;
elem_type type;
} generic_element_descriptor;
generic_element_descriptor foo_descriptor[] = {
{"string_data", /* How do I get sizeof string_data? */, offsetof(foo, string_data), elem_type_string},
... etc. one for each struct element ...
};
--------
Do you see what I am asking? I could do: sizeof(char[100])
But I was hoping for something more like offsetof which
doesn't need the type, only the struct member name.
Any thoughts?
-bluejack
/* ------------------------------------------------------------------ *\
| http://www.bluejack.com || reviews of science fiction |
| || record of the writing life |
\* ------------------------------------------------------------------ */
> I have a sinking suspicion that I can't do this in an aesthetically
> pleasing way, but maybe someone has an idea:
>
> typdef enum {
"typedef"
> elem_type_string;
> elem_type_int;
> elem_type_double;
Assume you mean commas instead of semicolons here. Also in C90 a
trailing comma (or semicolon) is not allowed within an enum.
> } elem_type;
>
> typedef struct {
> char string_data[100];
> int num_data;
> double float_data;
> } foo;
>
[...]
> generic_element_descriptor foo_descriptor[] = {
> {"string_data", /* How do I get sizeof string_data? */, offsetof(foo, string_data), elem_type_string},
> ... etc. one for each struct element ...
> };
You could do something like this:
foo foo_instance;
...sizeof (foo_instance.string_data)...
Certain compilers may also accept something like
sizeof (sizeof ((foo *) 0)->string_data)
but I'd never try that in code intended to be portable. I
haven't looked up a clause that says it's undefined but it
definitely has no place in an "aesthetically pleasing" program.
--
"Your correction is 100% correct and 0% helpful. Well done!"
--Richard Heathfield
>typedef struct {
> char string_data[100];
> int num_data;
> double float_data;
>} foo;
>
>typedef struct {
> char* element_name;
> size_t element_size;
> size_t element_offset;
> elem_type type;
>} generic_element_descriptor;
>
>generic_element_descriptor foo_descriptor[] = {
> {"string_data", /* How do I get sizeof string_data? */, offsetof(foo,
>string_data), elem_type_string},
> ... etc. one for each struct element ...
>};
>
>--------
>
> Do you see what I am asking? I could do: sizeof(char[100])
> But I was hoping for something more like offsetof which
> doesn't need the type, only the struct member name.
>
> Any thoughts?
If you have an object of type foo in scope, you can use sizeof on the
appropriate member of that struct:
--------
dave@goofy:~/clc (0) $ cat bluejack.c
#include <stddef.h>
#include <stdio.h>
struct foo
{
char bar[100];
} the_foo;
size_t the_size=sizeof the_foo.bar;
int main(void)
{
printf("%lu\n",(unsigned long)the_size);
return 0;
}
dave@goofy:~/clc (0) $ gcc -W -Wall -ansi -pedantic -O bluejack.c
dave@goofy:~/clc (0) $ ./a.out
100
dave@goofy:~/clc (0) $
--------
If you don't have an appropriate object in your code then adding one
probably won't meet your requirement that it be aesthetically pleasing,
but if you have a global object of the appropriate type you may be able
to get away with making sure its declaration is placed appropriately.
dave
--
Dave Vandervies dj3v...@calum.csclub.uwaterloo.ca
The news server I'm using has be+en lately demonstrating the odd behavior of
adding + characters here and there. Particularly in pairs, after a capital
C++, when posting to the comp.lang.c newsgroup. --Kaz Kylheku in comp.lang.c
...
>Certain compilers may also accept something like
> sizeof (sizeof ((foo *) 0)->string_data)
>but I'd never try that in code intended to be portable. I
This is a correct, portable construct since sizeof's operand here is
not evaluated.
>haven't looked up a clause that says it's undefined but it
>definitely has no place in an "aesthetically pleasing" program.
If you are unhappy with the look of it define a macro in a similar style
to offsetof().
#define MEMBSIZE(s, m) (sizeof ((s *)0)->m)
This has the same limitations on its arguments as offsetof().
--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------
This is a very interesting statement, but i don't understand it completely.
I don't understand the "sizeof((foo *) 0)". What's the "0" for?
Can someone explain it to me please? Thanks!
Sean
This expression is equivalent to sizeof(size_t)
> I don't understand the "sizeof((foo *) 0)". What's the "0" for?
> Can someone explain it to me please? Thanks!
sizeof((foo *)0) yields the size of an object of type (foo *). Note that
this has nothing to do with the expression above. You should read the
expression above as sizeof(sizeof(((foo *)0)->string_data)), where
sizeof(((foo *)0)->string_data) yield the size of an object of the type
equal to the type of foo.string_data.
The sizeof operator must be invoked in one of three ways:
1. sizeof(type), where type can be a built-in type like int or
double, or any defined complete type such as a structure, union,
array. In this case the parentheses are necessary.
2. sizeof object, where object is a either a defined instance of a
complete type. Here parentheses are optional but not required.
3. sizeof *pointer, where pointer has a defined type of pointer to a
complete type. Again in this case parentheses are not optional.
Now given the following declarations:
double d;
double *dp;
struct ds
{
double dm;
} DS;
You can do the following:
sizeof(double) /* sizeof applied to type */
sizeof d /* sizeof applied to object */
sizeof *dp /* sizeof applied to type of pointed to object */
sizeof struct ds /* sizeof applied to type */
sizeof DS /* sizeof applied to object */
...but what you can't do is:
sizeof struct ds.dm /* struct member is not a type */
To apply the sizeof operator to a member of a struct or union, you
need to supply an instance of the object or a pointer to the object so
you can apply either the "sizeof object" or "sizeof what is pointed to
by pointer".
At the point in bluejack's code where he needs the size of his
particular structure to initialize data, he does not have either an
object of this type defined, or a pointer to this type defined.
Here's where the particular property of the sizeof operator comes to
the rescue. Prior to C99, sizeof is specifically defined no to
evaluate its operand. It is a compile time operator that is replaced
with a compile time constant, it doesn't really exist at run time and
never accesses the operand.
This has been slightly changed in C99, since VLAs (variable length
arrays) have been added, whose size is not known until they are
created at run time. In the case of applying sizeof to a VLA in a C99
program, the sizeof operator must operate at run time. But in all
other cases, even in C99, sizeof evaluates to a constant at compile
time and does not evaluate the object in any way, shape, or form. The
operand, if not a type, is only analyzed at compile time to determine
what type is represents.
So sizeof ((struct ds *)0)->dm is a perfectly legitimate use of the
sizeof operator. Casting a 0 (or the macro NULL) to a pointer to a
struct ds and appending the ->dm gives the compiler the information it
needs to determine the type involved, the dm member of a struct ds in
my example, an array of 100 chars in the OP's example. So the
compiler, at compile type, replaces the sizeof operator with a
constant of type size_t that equals the asked for value.
Note that dereferencing ((struct ds *)0)->dm at run time would of
course invoke undefined behavior, but sizeof never actually performs
such an access.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
> The sizeof operator must be invoked in one of three ways:
>
> 1. sizeof(type), where type can be a built-in type like int or
> double, or any defined complete type such as a structure, union,
> array. In this case the parentheses are necessary.
>
> 2. sizeof object, where object is a either a defined instance of a
> complete type. Here parentheses are optional but not required.
>
> 3. sizeof *pointer, where pointer has a defined type of pointer to a
> complete type. Again in this case parentheses are not optional.
There is really no difference between your second and third
cases. They are both special cases of `sizeof
<unary-expression>', covered by a single production in the
grammar. Also I think you mean `...are optional' in the third
case; *pointer is not a type-name.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x1f6},*p=
b,x,i=24;for(;p+=!*p;*p/=4)switch(x=*p&3)case 0:{return 0;for(p--;i--;i--)case
2:{i++;if(1)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
Thanks, Jack, and everyone. This was a very illuminating
discussion, and solved my problem.
>Jack Klein <jack...@spamcop.net> writes:
>
>> The sizeof operator must be invoked in one of three ways:
>>
>> 1. sizeof(type), where type can be a built-in type like int or
>> double, or any defined complete type such as a structure, union,
>> array. In this case the parentheses are necessary.
>>
>> 2. sizeof object, where object is a either a defined instance of a
>> complete type. Here parentheses are optional but not required.
>>
>> 3. sizeof *pointer, where pointer has a defined type of pointer to a
>> complete type. Again in this case parentheses are not optional.
>
>There is really no difference between your second and third
>cases. They are both special cases of `sizeof
><unary-expression>', covered by a single production in the
>grammar. Also I think you mean `...are optional' in the third
>case; *pointer is not a type-name.
Right, the operand of sizeof doesn't have to be a type or an object,
any expression with object type will do (some may have to be enclosed
in parentheses to get the desired parsing). So, for example sizeof(0/0)
and just plain sizeof 42 are equivalent to sizeof(int).