473,405 Members | 2,344 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

std::vector and structs of PODs

I have ome new code which has to work with some legacy code which does
a lot of memset's and memcmp's on structs of PODs. This leads me to
want to do stuff like this:

struct foo
{
unsigned char c1_;
unsigned short us1_;
};

std::vector<foo> fooVect;
memset(&foo, 0, sizeof(foo));
fooVect.push_back(foo);

The compiler I've tested this with uses 4 byte alignment by default and
hence puts in some padding bytes. Looking at the copy of foo which is
now at fooVect[0], the padding bytes have random values. The zero
setting of the padding bytes has not been preserved when foo has been
copied to the vector.

I'd expect that what happens to padding bytes is undefined, but it
would be useful to have them preserved as zero. Any sensible,
non-kludgy, portable way of doing this?

--
Simon Elliott http://www.ctsn.co.uk
Jul 23 '05 #1
6 2938
Simon Elliott wrote:
I have ome new code which has to work with some legacy code which does
a lot of memset's and memcmp's on structs of PODs. This leads me to
want to do stuff like this:

struct foo
{
unsigned char c1_;
unsigned short us1_;
};

std::vector<foo> fooVect;
memset(&foo, 0, sizeof(foo));
fooVect.push_back(foo);

The compiler I've tested this with uses 4 byte alignment by default and
hence puts in some padding bytes. Looking at the copy of foo which is
now at fooVect[0], the padding bytes have random values. The zero
setting of the padding bytes has not been preserved when foo has been
copied to the vector.

I'd expect that what happens to padding bytes is undefined, but it
would be useful to have them preserved as zero.
How would it be useful? I am genuinely curious.
Any sensible,
non-kludgy, portable way of doing this?


I don't think so. If you know what the size of 'foo' is with your current
alignment requirements, you could add

char padding[known_size_of_foo - sizeof(short) - 1];

To know what the size of 'foo' is, you need to replicate it

struct foo_replica {
char c; short s;
};

and use *its* size instead. Basically it should be

struct foo_replica
{
char c; short s;
};

struct foo
{
unsigned char c1_;
unsigned short us1_;
char padding[sizeof(foo_replica) - 1 - sizeof(short)];
};

Victor
Jul 23 '05 #2
Simon Elliott wrote:

I have ome new code which has to work with some legacy code which does
a lot of memset's and memcmp's on structs of PODs. This leads me to
want to do stuff like this:

struct foo
{
unsigned char c1_;
unsigned short us1_;
};

std::vector<foo> fooVect;

memset(&foo, 0, sizeof(foo));
fooVect.push_back(foo);

The compiler I've tested this with uses 4 byte alignment by default and
hence puts in some padding bytes. Looking at the copy of foo which is
now at fooVect[0], the padding bytes have random values. The zero
setting of the padding bytes has not been preserved when foo has been
copied to the vector.

I'd expect that what happens to padding bytes is undefined, but it
would be useful to have them preserved as zero. Any sensible,
non-kludgy, portable way of doing this?


struct foo
{
foo() { memset( this, 0, sizeof( foo ) ); }
foo( const foo& Arg ) { memcpy( this, Arg, sizeof( foo ) ); }

unsigned char c1_;
unsigned short us1_;
};

But note: This works as long as data members of that struct qualify
the struct as a POD (It is no longer one, since a POD doesn't have
a ctor). At the moment somebody introdues a std::string or any other
class with dynamic management in it, it will fail miserably.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 23 '05 #3
Simon Elliott wrote:
The compiler I've tested this with uses 4 byte alignment by default and hence puts in some padding bytes. Looking at the copy of foo which is
now at fooVect[0], the padding bytes have random values.
Sure but who cares? You can neither access these bytes nor take
any advantage of them: they are an implementation detail of the
compiler, nothing more. They might highlight some programming
errors, though: e.g. they may cause unterminated C-strings to
become terminated.
I'd expect that what happens to padding bytes is undefined, but it
would be useful to have them preserved as zero.


Why?
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting

Jul 23 '05 #4
On 23/02/2005, Victor Bazarov wrote:
I'd expect that what happens to padding bytes is undefined, but it
would be useful to have them preserved as zero.


How would it be useful? I am genuinely curious.


Down in the legacy code, memcmp() is used extensively to compare these
things. Unfortunately, memcmp() will compare things like padding bytes,
trailing bytes in C strings etc. So either I find a way of doing this,
or I have to make some significant changes to legacy code.
Any sensible,
non-kludgy, portable way of doing this?


I don't think so. If you know what the size of 'foo' is with your
current alignment requirements, you could add

char padding[known_size_of_foo - sizeof(short) - 1];

To know what the size of 'foo' is, you need to replicate it

struct foo_replica {
char c; short s;
};

and use its size instead. Basically it should be

struct foo_replica
{
char c; short s;
};

struct foo
{
unsigned char c1_;
unsigned short us1_;
char padding[sizeof(foo_replica) - 1 - sizeof(short)];
};


I'm not convinced that this will work because the compiler inserts
padding bytes between c1_ and us1_ so that they align optimally for the
target processor (4 byte boundaries I think in the case of the compiler
I'm using at the moment.) However, perhaps I could do something along
similar lines:

struct foo_holder
{
union
{
foo foo_;
char padding_[sizeof(foo)];
}
};

Then my vector would be a vector of foo_holder, and I'd pass
foo_holder::foo_ down to the legacy code. I expect I could have a
templated holder struct which could hold all the legacy structs.

Or I could push an undefined foo onto the vector, and do something
like:
memset(&fooVect.back(), 0, sizeof(foo));
then fill in foo's fields as referenced by fooVect.back()

--
Simon Elliott http://www.ctsn.co.uk
Jul 23 '05 #5
Simon Elliott wrote:
Down in the legacy code, memcmp() is used extensively to compare these things. Unfortunately, memcmp() will compare things like padding bytes, trailing bytes in C strings etc. So either I find a way of doing this, or I have to make some significant changes to legacy code.
Hm, OK. I don't think this is the best way to it but it seems like a
reasonable request. Do you need to pass (pointers to) arrays of your
type? If not, you could use something like this:

/**/ struct wrapper
/**/ {
/**/ wrapper() { std::memset(&m_foo, 0, sizeof(foo)); }
/**/ wrapper(wrapper const& w) {
/**/ std::memcpy(&m_foo, &w.mem_foo, sizeof(foo));
/**/ foo m_foo;
/**/ };

Even if you need arrays of 'foo's, you might be able to use this
wrapper technique, if 'sizeof(wrapper) == sizeof(foo)': you could
just reinterpret_cast to the appropriate type...
However, perhaps I could do something along similar lines:

struct foo_holder
{
union
{
foo foo_;
char padding_[sizeof(foo)];
}
};


Why use a union? If you use a wrapper, use it with appropriate
constructors...
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting

Jul 23 '05 #6
"Dietmar Kuehl" <di***********@yahoo.com> writes:
Simon Elliott wrote:
The compiler I've tested this with uses 4 byte alignment by default

and
hence puts in some padding bytes. Looking at the copy of foo which is
now at fooVect[0], the padding bytes have random values.


Sure but who cares? You can neither access these bytes nor take
any advantage of them: they are an implementation detail of the
compiler, nothing more. They might highlight some programming
errors, though: e.g. they may cause unterminated C-strings to
become terminated.
I'd expect that what happens to padding bytes is undefined, but it
would be useful to have them preserved as zero.


Why?


It can help hide programming errors. Remember, the longer a
programming error goes undected, the more chances it has to cause
an embarassing crash during a demo.
Jul 23 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

27
by: Jason Heyes | last post by:
To my understanding, std::vector does not use reference counting to avoid the overhead of copying and initialisation. Where can I get a reference counted implementation of std::vector? Thanks.
18
by: Janina Kramer | last post by:
hi ng, i'm working on a multiplayer game for a variable number of players and on the client side, i'm using a std::vector<CPlayer> to store informatik about the players. CPlayer is a class that...
20
by: Anonymous | last post by:
Is there a non-brute force method of doing this? transform() looked likely but had no predefined function object. std::vector<double> src; std::vector<int> dest; ...
17
by: Michael Hopkins | last post by:
Hi all I want to create a std::vector that goes from 1 to n instead of 0 to n-1. The only change this will have is in loops and when the vector returns positions of elements etc. I am calling...
8
by: Ross A. Finlayson | last post by:
I'm trying to write some C code, but I want to use C++'s std::vector. Indeed, if the code is compiled as C++, I want the container to actually be std::vector, in this case of a collection of value...
32
by: zl2k | last post by:
hi, c++ user Suppose I constructed a large array and put it in the std::vector in a function and now I want to return it back to where the function is called. I can do like this: ...
56
by: Peter Olcott | last post by:
I am trying to refer to the same std::vector in a class by two different names, I tried a union, and I tried a reference, I can't seem to get the syntax right. Can anyone please help? Thanks
9
by: aaragon | last post by:
I am trying to create a vector of type T and everything goes fine until I try to iterate over it. For some reason, the compiler gives me an error when I declare std::vector<T>::iterator iter;...
13
by: jubelbrus | last post by:
Hi I'm trying to do the following. #include <vector> #include <boost/thread/mutex.hpp> #include <boost/shared_ptr.hpp> #include <boost/tuple/tuple.hpp> class {
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.