Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   sizeof(struct dirent.d_ino) (http://www.velocityreviews.com/forums/t315156-sizeof-struct-dirent-d_ino.html)

Martin Pohlack 09-08-2003 01:59 PM

sizeof(struct dirent.d_ino)
 
Hi,

I have a funtion which shall compute the amount for a later malloc. In
this function I need the sizes of some struct members without having an
instance or pointer of the struct.

As "sizeof(int)" is legal I assumed "sizeof(struct x.y)" to be legal
too. But is is not:

#include <dirent.h>

int dir_dirent_size(dir_t * dirp)
{
int len;

// syntax error
len = sizeof(struct dirent.d_ino) +
sizeof(struct dirent.d_off) +
sizeof(struct dirent.d_reclen) +
strlen(dirp->name) + 1;

return len;
}


I can fix this problem using a dummy pointer to a dirent struct:

#include <dirent.h>

int dir_dirent_size(dir_t * dirp)
{
int len;
struct dirent * temp;

// syntax error
len = sizeof(temp.d_ino) +
sizeof(temp.d_off) +
sizeof(temp.d_reclen) +
strlen(dirp->name) + 1;

return len;
}


However, I'm curious what would be the 'right thing' (tm) to do.

Thank you,
Martin Pohlack


Irrwahn Grausewitz 09-08-2003 03:04 PM

Re: sizeof(struct dirent.d_ino)
 
Martin Pohlack <mp26@inf.tu-dresden.de> wrote:

>Hi,
>
>I have a funtion which shall compute the amount for a later malloc. In
>this function I need the sizes of some struct members without having an
>instance or pointer of the struct.
>
>As "sizeof(int)" is legal I assumed "sizeof(struct x.y)" to be legal
>too. But is is not:
>
>#include <dirent.h>
>
>int dir_dirent_size(dir_t * dirp)
>{
> int len;
>
> // syntax error
> len = sizeof(struct dirent.d_ino) +
> sizeof(struct dirent.d_off) +
> sizeof(struct dirent.d_reclen) +
> strlen(dirp->name) + 1;
>
> return len;
>}
>
>
>I can fix this problem using a dummy pointer to a dirent struct:
>
>#include <dirent.h>


This is a non-standard header. Anyway, I suppose it declares
(at least) the struct dirent you are referring to later...

>
>int dir_dirent_size(dir_t * dirp)
>{
> int len;
> struct dirent * temp;
>
> // syntax error
> len = sizeof(temp.d_ino) +
> sizeof(temp.d_off) +
> sizeof(temp.d_reclen) +
> strlen(dirp->name) + 1;
>
> return len;
>}
>
>
>However, I'm curious what would be the 'right thing' (tm) to do.


You should change the above to:

len = sizeof temp->d_ino +
sizeof temp->d_off +
sizeof temp->d_reclen +
...

as temp is a *pointer* to a struct and the parantheses are optional,
when applying the sizeof operator to an object, not a type.

Further more, if your intention is to calculate the size of the /whole/
struct, inclusive possible padding, you should just write:

len = sizeof *temp +
...

Regards,

Irrwahn
--
New funsports: inline climbing

Martin Pohlack 09-08-2003 07:54 PM

Re: sizeof(struct dirent.d_ino)
 
First of all, thank you for your answer.

Irrwahn Grausewitz wrote:
> Martin Pohlack <mp26@inf.tu-dresden.de> wrote:
>
>
>> Hi,
>>
>> I have a funtion which shall compute the amount for a later malloc.
>> In this function I need the sizes of some struct members without
>> having an instance or pointer of the struct.
>>
>> As "sizeof(int)" is legal I assumed "sizeof(struct x.y)" to be
>> legal too. But is is not:
>>
>> #include <dirent.h>
>>
>> int dir_dirent_size(dir_t * dirp) { int len;
>>
>> // syntax error len = sizeof(struct dirent.d_ino) + sizeof(struct
>> dirent.d_off) + sizeof(struct dirent.d_reclen) + strlen(dirp->name)
>> + 1;
>>
>> return len; }
>>
>>
>> I can fix this problem using a dummy pointer to a dirent struct:
>>
>> #include <dirent.h>

>
> This is a non-standard header. Anyway, I suppose it declares (at
> least) the struct dirent you are referring to later...



yes, the struct is declared there, but that should not be important for
my example. Anyway, the struct looks like follows:

struct dirent
{
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[256];
};


>> int dir_dirent_size(dir_t * dirp) { int len; struct dirent * temp;
>>
>> // syntax error len = sizeof(temp.d_ino) + sizeof(temp.d_off) +
>> sizeof(temp.d_reclen) + strlen(dirp->name) + 1;
>>
>> return len; }
>>
>>
>> However, I'm curious what would be the 'right thing' (tm) to do.

>
>
> You should change the above to:
>
> len = sizeof temp->d_ino + sizeof temp->d_off + sizeof temp->d_reclen
> + ...
>
> as temp is a *pointer* to a struct and the parantheses are optional,
> when applying the sizeof operator to an object, not a type.



yes, you are right. I must confess I constructed the example without of
trying to recompile it after the last changes. So, what you wrote is
what I head in mind ;-). However, optional is not the same as forbidden.
So I consider the question of parantheses as a question of style.


> Further more, if your intention is to calculate the size of the
> /whole/ struct, inclusive possible padding, you should just write:
>
> len = sizeof *temp + ...



Yes, of course that is what I *would* do. But I don't want that.

I want to compute the size of *parts* of the struct *without* of having
an instance of it, as it is possible to compute the size of an int by
writing:

x = sizeof(int);

On the contrary it is possible to do it with an instance:


int a;
x = sizeof(x);

or

int *a;
x = sizeof(*a);

For more complex types it only seems to be possible to use one of the
last cases.

Or is there a way???


btw. a (local) friend of mine suggested the following:

len = sizeof (((struct dirent *) 0)->d_ino);


greets,
Martin


Martin Dickopp 09-08-2003 09:23 PM

Re: sizeof(struct dirent.d_ino)
 
Martin Pohlack <mp26@os.inf.tu-dresden.de> writes:

> I want to compute the size of *parts* of the struct *without* of having
> an instance of it,


Why?

If your only concern is wasted space, I wouldn't worry about it. An
instance of a structure which is not used except that its members are
operands to the `sizeof' operator is likely to be optimized away by
the compiler.

If you have another reason, read on...

> btw. a (local) friend of mine suggested the following:
>
> len = sizeof (((struct dirent *) 0)->d_ino);


This causes undefined behavior. However, you could use the `offsetof'
macro (defined in <stddef.h>) which yields the offset of a structure
member from the beginning of the structure. If you have, for example,

struct foo {
int bar;
long baz;
float blah;
double blub;
void *platsch;
};

then the expression

offsetof (struct foo, blub) - offsetof (struct foo, blah)

yields the size of `blah', and

sizeof (struct foo) - offsetof (struct foo, platsch)

yields the size of `platsch'.

Martin

Udo A. Steinberg 09-08-2003 10:04 PM

Re: sizeof(struct dirent.d_ino)
 
On 08 Sep 2003 23:23:33 +0200 Martin Dickopp (MD) wrote:

Hi,

MD> If your only concern is wasted space, I wouldn't worry about it. An
MD> instance of a structure which is not used except that its members are
MD> operands to the `sizeof' operator is likely to be optimized away by
MD> the compiler.

Agreed.

MD> > len = sizeof (((struct dirent *) 0)->d_ino);
MD>
MD> This causes undefined behavior.

Can you elaborate on why this is undefined behaviour? It is implemented
in a similar manner to the offsetof macro.

MD> offsetof (struct foo, blub) - offsetof (struct foo, blah)
MD>
MD> yields the size of `blah', and

Tricks like this rely on the order of structure members being known and
never changing which is why we considered it sub-optimal.

-Udo.

Irrwahn Grausewitz 09-08-2003 11:05 PM

Re: sizeof(struct dirent.d_ino)
 
Martin Pohlack <mp26@os.inf.tu-dresden.de> wrote:
<SNIP>
>However, optional is not the same as forbidden.
>So I consider the question of parantheses as a question of style.

Agreed.

<SNIP>
>
>I want to compute the size of *parts* of the struct *without* of having
>an instance of it

I have to accept that that's what you want, but may I ask what's so
terrible on having an instance of, or, at least, a pointer to the type
you want to know the size of? What's the reason for the restriction?

<SNIP>
> int a;
> x = sizeof(x);

^^^
That's hopefully just a typo... :^)

<SNIP>
>btw. a (local) friend of mine suggested the following:
>
> len = sizeof (((struct dirent *) 0)->d_ino);
>

Hm, this looks like a legal C construct, as it does not dereference
the NULL pointer AFAICS, but I'm not among the experts, so maybe I'm
terribly wrong on this...

Irrwahn
--
Close your eyes and press escape three times.

Mark Gordon 09-08-2003 11:45 PM

Re: sizeof(struct dirent.d_ino)
 
On Tue, 9 Sep 2003 00:04:56 +0200
"Udo A. Steinberg" <us15@os.inf.tu-dresden.de> wrote:

> On 08 Sep 2003 23:23:33 +0200 Martin Dickopp (MD) wrote:
>
> Hi,
>
> MD> If your only concern is wasted space, I wouldn't worry about it.
> MD> An instance of a structure which is not used except that its
> MD> members are operands to the `sizeof' operator is likely to be
> MD> optimized away by the compiler.
>
> Agreed.
>
> MD> > len = sizeof (((struct dirent *) 0)->d_ino);
> MD>
> MD> This causes undefined behavior.
>
> Can you elaborate on why this is undefined behaviour? It is
> implemented in a similar manner to the offsetof macro.


The implementation is allowed to use any non-standard tricks it like in
the headers it provides since those headers are only for that
implementation. It could even have special magic in the compiler to make
those headers work without making the same tricks work in user generated
code.

In the example above the null pointer is being dereferenced so it is
undefined behaviour in any code you write.

You could always use something like
{
struct dirent dummy;
len = sizeof dummy.d_ino;
}

I would not expect any decent compiler to allocate space for dummy.

> MD> offsetof (struct foo, blub) - offsetof (struct foo, blah)
> MD>
> MD> yields the size of `blah', and
>
> Tricks like this rely on the order of structure members being known
> and never changing which is why we considered it sub-optimal.


It also has the potential to give a different result since there might
be padding between the end of blah and the start of blub and does not
work for the last element since there is no member after it.
--
Mark Gordon

Martin Dickopp 09-08-2003 11:56 PM

Re: sizeof(struct dirent.d_ino)
 
"Udo A. Steinberg" <us15@os.inf.tu-dresden.de> writes:

> MD> > len = sizeof (((struct dirent *) 0)->d_ino);
> MD>
> MD> This causes undefined behavior.
>
> Can you elaborate on why this is undefined behaviour?


Standard section 6.5.2.3#4 defines the behavior of the `->' operator
only for the case that the left operand points to an object, which a
null pointer of type `struct dirent *' does not. Section 4#2 makes it
clear that whenever no behavior is defined explicitly, the behavior
is undefined.

> It is implemented in a similar manner to the offsetof macro.


The standard doesn't define how the `offsetof' is implemented.

Many C implementations do in fact apply the `->' operator to a null
pointer of appropriate type, but that doesn't mean it's also valid in
user code. :) The language implementor knows what extensions his
implementation supports and is therefore not bound by the standard.
In fact, I don't think there's any portable way to achive the effect
of the `offsetof' macro without actually using it.

> MD> offsetof (struct foo, blub) - offsetof (struct foo, blah)
> MD>
> MD> yields the size of `blah', and
>
> Tricks like this rely on the order of structure members being known and
> never changing which is why we considered it sub-optimal.


I agree. Which brings me back to the question of what you (or rather the
OP, but you seem to be affiliated with the same TUD institute, so can I
assume you work on the same thing?) are trying to achieve?

Martin

Martin Dickopp 09-09-2003 12:02 AM

Re: sizeof(struct dirent.d_ino)
 
Irrwahn Grausewitz <irrwahn@freenet.de> writes:

> Martin Pohlack <mp26@os.inf.tu-dresden.de> wrote:
>
> > len = sizeof (((struct dirent *) 0)->d_ino);
> >

> Hm, this looks like a legal C construct, as it does not dereference
> the NULL pointer AFAICS,


It doesn't dereference the null pointer, since the operand of the `sizeof'
operator is not evaluated. But according to my understanding of the
standard, the behavior is still undefined. See my other posting in this
thread.

Martin

Martin Dickopp 09-09-2003 12:20 AM

Re: sizeof(struct dirent.d_ino)
 
Mark Gordon <spamtrap@flash-gordon.me.uk> writes:

> On Tue, 9 Sep 2003 00:04:56 +0200
> "Udo A. Steinberg" <us15@os.inf.tu-dresden.de> wrote:
>
> > On 08 Sep 2003 23:23:33 +0200 Martin Dickopp (MD) wrote:
> >
> > Hi,
> >
> > MD> If your only concern is wasted space, I wouldn't worry about it.
> > MD> An instance of a structure which is not used except that its
> > MD> members are operands to the `sizeof' operator is likely to be
> > MD> optimized away by the compiler.
> >
> > Agreed.
> >
> > MD> > len = sizeof (((struct dirent *) 0)->d_ino);
> > MD>
> > MD> This causes undefined behavior.

>
> In the example above the null pointer is being dereferenced so it is
> undefined behaviour in any code you write.


I don't think the null pointer is dereferenced, as the operand of the
`sizeof' operator is not evaluated. I believe it to be undefined behavior
because the standard only defines the behavior of `->' when its left
operand points to an object (6.5.2.3#4).

> > MD> offsetof (struct foo, blub) - offsetof (struct foo, blah)
> > MD>
> > MD> yields the size of `blah', and
> >
> > Tricks like this rely on the order of structure members being known
> > and never changing which is why we considered it sub-optimal.

>
> It also has the potential to give a different result since there might
> be padding between the end of blah


Correct.

> and the start of blub and does not work for the last element since there
> is no member after it.


But there /is/ a member after the last one - don't you see it? ;)
Its offset from the beginning of the structure is `sizeof (struct foo)'.

Martin


All times are GMT. The time now is 07:03 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.