sizeof unpadded struct size

P

Phil Carmody

James Kuyper said:
I assumed that he wanted a simple way to get that same number without
explicitly performing the sum. I can't see any reason to make any more
complicated assumption, unless and until he says something more
specific about what he wants.

I've needed to do almost precisely what I've mentioned in a RAM-
limited embedded environment. I don't view the assumption that
he might want to be doing the same to be a "more complicated" one.
The situation where one might make use of my construction is in
fact a far _simpler_ one than the situation where one would make
use of yours, if you think about it. Placing an irregular shape
in a grid is far simpler than tessalating it, is it not?

Phil
 
J

James Kuyper

Phil said:
I've needed to do almost precisely what I've mentioned in a RAM-
limited embedded environment. I don't view the assumption that
he might want to be doing the same to be a "more complicated" one.

I've never had need of that number; the only ways I can think of to use
it involve undefined behavior.

I have had situations where the number I mentioned would have been
useful, when packing a struct into an array of unsigned char. If there
had existed an packed_sizeof, my code could have been marginally
simplified by making use of it as in the following simplified example,
which references the struct abc provided by the OP:

int pack_abc(FILE *output, struct abc *padded)
{
unsigned char packed[packed_sizeof(struct abc)];
unsigned char *p = packed;

memcpy(p, &padded->z), sizeof padded->z);
p += sizeof padded->z;

memcpy(p, &padded->y), sizeof padded->y);
p += sizeof padded->y;

memcpy(p, &padded->x), sizeof padded->x);

return fwrite(packed, 1, sizeof packed, output);
}

In the actual case where I had to do something this, the equivalent of
the fwrite() function was actually a third-party library routine, which
by a different route required a text string describing the types of the
objects that had been packed into the buffer - similar in concept
(though not in syntax) to the format strings used by the
printf()/scanf() family. The structure had sufficiently many fields that
it made sense to combine the memcpy() and the p+= into a single macro.
However, I didn't want to complicate things by showing those details.

Note: the advantage provided by having a packed_sizeof in this case is
quite minor, and I wouldn't advocate it's addition to the standard, but
I could easily imagine someone else wanting such a thing for similar uses.
 
P

Phil Carmody

James Kuyper said:
I've never had need of that number; the only ways I can think of to
use it involve undefined behavior.

I'm pretty sure that what I was doing had no UB, both in the standard
at the time and now. It was simply a cache for (sets of) small objects.
I have had situations where the number I mentioned would have been
useful, when packing a struct into an array of unsigned char. If
there had existed an packed_sizeof, my code could have been marginally
simplified by making use of it as in the following simplified example,
which references the struct abc provided by the OP:

int pack_abc(FILE *output, struct abc *padded)

The problem with this is that you need a different function for
each struct that you'll be streaming (or caching in my case).
That would have been too wasteful of code space. A single extra
parameter providing the "diameter" (I'll avoid the term 'size'
;-) ) of the data in the structure, and you can stash or restore
with a simple fwrite/memcpy. Yup, not always quite as space
efficient as completely packing each structure, which you've
done, but in the code space/data space/time tradeoff, it's what
we settled on. I suspect we had next to no internal padding in
structures by design anyway.
Note: the advantage provided by having a packed_sizeof in this case is
quite minor, and I wouldn't advocate it's addition to the standard,
but I could easily imagine someone else wanting such a thing for
similar uses.

I agree that such uses are marginal, and not worth the whole C
community fretting over. Given the fuzziness of the original
question. We can't even be sure what he actually *needs* anyway.

Phil
 
S

sinbad

With respect, Bartc, I want sinbad's answer, not yours.

You make the same assumption they do: that there is a "true size"
different from the /actual/ size, viz, the size that sizeof says.
Whether the number 9 means anything /useful/ with respect to the
size of struct abc we don't know.


I would not be so sure. If there is only one struct /whose address is
not taken/, that I might grant. In that case, the compiler can likely
as-if the extra bytes away.


The other aspect of my "why" is "if you knew the answer, what would you
do with it?". At this stage, only sinbad knows.

--
"We dance, and the worlds melt away."             - Curved Air, /Metamorphosis/

Hewlett-Packard Limited                                          registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN          690597 England


All,
sorry for late reply;

The reason why i needed to know unpadded struct size is as follows.

Suppose if i want to transport an instance of the struct abc type to
other process for some reason,i do this way, i will keep the data into
a contigous buffer,here as i keep the individual elements in to the
buffer and calculate the size accordingly with the size of data item
actully copied into the buffer.The data size in the buffer would be
9 bytes and not 12; The size value 9 is computed while i place the
data
into the buffer so i always get the unpadded size. Now the problem is
at
the receiving process, the receiving process gets the buffer, length
of
the buffer and the type of the data (some type value which tells the
receiving
process that the data is of struct abc type), So the receiving process
should
validate the size value, As it knows that the data is of struct abc
type,
it expects that the data size shouldn't be less than sizeof(struct
abc),
Here's the catch, the size value passed by the sending process is 9
which
is less than sizeof(struct abc) which is 12, so the process interprets
the message
as corrupted and drops it. The following code snippet explains it.

#define TYPE_STRUCT_ABC 1
#define put_buf (m) (memcpy (buf, m, sizeof(m)) \
size += sizeof(m) \
buf += sizeof(m)

int
send_data (char *buf)
{
int size;
struct abc a;
put_buf (a.x);
put_buf (a.y);
put_buf (a.z);
send_data (buf, size, TYPE_STRUCT_ABC);

return 0;
}

int
recv_data (char *buf, int size, type)
{
if (type == TYPE_STRUCT_ABC)
{
if (size < sizeof(struct abc))
{
/* size is not as expected */
return -1;
}
}

process_data (buf, size);
return 0;
}

thanks
 
C

Chris Dollin

sinbad said:
Now the problem is
at
the receiving process, the receiving process gets the buffer, length
of
the buffer and the type of the data (some type value which tells the
receiving
process that the data is of struct abc type), So the receiving process
should
validate the size value, As it knows that the data is of struct abc
type,
it expects that the data size shouldn't be less than sizeof(struct
abc),
Here's the catch, the size value passed by the sending process is 9
which
is less than sizeof(struct abc) which is 12, so the process interprets
the message
as corrupted and drops it.

Essentially, then, there's a bug in that code: it makes false assumptions.

Rather than trying to work out how to replicate the false assumption,
wouldn't it be better to fix that code?
 
J

James Kuyper

sinbad said:
Suppose if i want to transport an instance of the struct abc type to
other process for some reason,i do this way, i will keep the data into
a contigous buffer,here as i keep the individual elements in to the
buffer and calculate the size accordingly with the size of data item
actully copied into the buffer.The data size in the buffer would be
9 bytes and not 12; The size value 9 is computed while i place the
data
into the buffer so i always get the unpadded size. Now the problem is
at
the receiving process, the receiving process gets the buffer, length
of
the buffer and the type of the data (some type value which tells the
receiving
process that the data is of struct abc type), So the receiving process
should
validate the size value, As it knows that the data is of struct abc
type,
it expects that the data size shouldn't be less than sizeof(struct
abc),
Here's the catch, the size value passed by the sending process is 9
which
is less than sizeof(struct abc) which is 12, so the process interprets
the message
as corrupted and drops it. The following code snippet explains it.

#define TYPE_STRUCT_ABC 1
#define put_buf (m) (memcpy (buf, m, sizeof(m)) \
size += sizeof(m) \
buf += sizeof(m)

int
send_data (char *buf)
{
int size;
struct abc a;
put_buf (a.x);
put_buf (a.y);
put_buf (a.z);

Why not just use

put_buf (a);

?

Then the size being passed would be 12, the correct value.
 
J

James Kuyper

sinbad said:
....
#define TYPE_STRUCT_ABC 1
#define put_buf (m) (memcpy (buf, m, sizeof(m)) \
size += sizeof(m) \
buf += sizeof(m)


Given the way you use put_buf below, shouldn't that be memcpy(buf, &m,
sizeof m) ?
 
B

Ben Bacarisse

[about sizeof unpadded struct size]
On Dec 17, 12:39 pm, Chris Dollin <[email protected]> wrote:

Is is better not to quote sigs.
sorry for late reply;

The reason why i needed to know unpadded struct size is as follows.

Suppose if i want to transport an instance of the struct abc type to
other process for some reason,i do this way, i will keep the data into
a contigous buffer,here as i keep the individual elements in to the
buffer and calculate the size accordingly with the size of data item
actully copied into the buffer.The data size in the buffer would be
9 bytes and not 12; The size value 9 is computed while i place the
data
into the buffer so i always get the unpadded size.

The obvious solution, then, is to calculate the size using the same
logic at the receiving end, but that might not be the best solution.
Now the problem is at the receiving process, the receiving process
gets the buffer, length of the buffer and the type of the data (some
type value which tells the receiving process that the data is of
struct abc type), So the receiving process should validate the size
value, As it knows that the data is of struct abc type, it expects
that the data size shouldn't be less than sizeof(struct abc),

As pointed out, one or other side has a bug then. Either you should
not expect the length to be less than the structure size (since it can
be, quite safely, less than that) or you should send the whole struct,
padding and all. Which fix is better depends on what you want.

I would suggest you unpack the message, checking the length as you go
rather than trying to report an error before unpacking. In other
words, reverse the logic of the packing code.

The reason I suggest this is that it opens the way to making the data
format independent of implementation at either end. You don't get
that advantage without more work, but removing the need to know how
one or both side has packed the structure is the first step.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,778
Messages
2,569,605
Members
45,238
Latest member
Top CryptoPodcasts

Latest Threads

Top