By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,797 Members | 1,794 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,797 IT Pros & Developers. It's quick & easy.

Accessing individual bytes of an integer

P: n/a
Hello!

I want to work with individual bytes of integers. I know that ints are
32-bit and will always be. Sometimes I want to work with the entire
32-bits, and other times I want to modify just the first 8-bits for
example. For me, I think it would be best if I can declare the 32-bits
like this:

unsigned char bits[4];

When I want to treat this as a 32-bits integer, can I do something
like this?

unsigned int bits32 = *((unsigned int*)bits);

I'm unsure of the syntax. I don't need to work in-place so to speak. It is
fine to work with a copy.

Thanks in advance!

--
Daniel

Jul 23 '05 #1
Share this Question
Share on Google+
27 Replies


P: n/a
"Daniel Lidström" <so*****@microsoft.com> wrote in message
news:pa****************************@microsoft.com. ..
When I want to treat this as a 32-bits integer, can I do something
like this?

unsigned int bits32 = *((unsigned int*)bits);


Yes you can, but you have absolutely no assurance as to what the results
will be :-)

What's wrong with

(bits>>n) & 0xff

where n is 0, 8, 16, or 24?
Jul 23 '05 #2

P: n/a

"Daniel Lidström" <so*****@microsoft.com> ????
news:pa****************************@microsoft.com. ..
Hello!

I want to work with individual bytes of integers. I know that ints are
32-bit and will always be. Sometimes I want to work with the entire
32-bits, and other times I want to modify just the first 8-bits for
example. For me, I think it would be best if I can declare the 32-bits
like this:

unsigned char bits[4];

When I want to treat this as a 32-bits integer, can I do something
like this?

unsigned int bits32 = *((unsigned int*)bits);

I'm unsure of the syntax. I don't need to work in-place so to speak. It is
fine to work with a copy.

Thanks in advance!

--
Daniel


Unconsidering the byte sequence, you are correct.
A better way is using a union like:
union xxx
{
unsigned char bits[4];
unsigned int i;
};
Jul 23 '05 #3

P: n/a
MatrixV wrote:
"Daniel Lidström" <so*****@microsoft.com> ????
news:pa****************************@microsoft.com. ..
Hello!

I want to work with individual bytes of integers. I know that ints are
32-bit and will always be. Sometimes I want to work with the entire
32-bits, and other times I want to modify just the first 8-bits for
example. For me, I think it would be best if I can declare the 32-bits
like this:

unsigned char bits[4];

When I want to treat this as a 32-bits integer, can I do something
like this?

unsigned int bits32 = *((unsigned int*)bits);

I'm unsure of the syntax. I don't need to work in-place so to speak. It is
fine to work with a copy.

Thanks in advance!

--
Daniel

Unconsidering the byte sequence, you are correct.
A better way is using a union like:
union xxx
{
unsigned char bits[4];
unsigned int i;
};


How about this:
union xxx
{
unsigned char bytes[sizeof(unsigned int))];
unsigned int i;
};
This makes no assumptions about how many bytes are
in an integer.
--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
http://www.sgi.com/tech/stl -- Standard Template Library

Jul 23 '05 #4

P: n/a
"MatrixV" <tr******@kcollege.com> wrote in message
news:37*************@individual.net...
Unconsidering the byte sequence, you are correct.
A better way is using a union like:
union xxx
{
unsigned char bits[4];
unsigned int i;
};


Not really. When you use a union, you have no assurance about the effect
that giving a value to one member of a union will have on other members.
Jul 23 '05 #5

P: n/a
MatrixV wrote:
"Daniel Lidström" <so*****@microsoft.com> ????

I want to work with individual bytes of integers. I know that ints are 32-bit and will always be. Sometimes I want to work with the entire
32-bits, and other times I want to modify just the first 8-bits for
example. For me, I think it would be best if I can declare the 32-bits like this:

unsigned char bits[4];

When I want to treat this as a 32-bits integer, can I do something
like this?

unsigned int bits32 = *((unsigned int*)bits);
Bad - if 'bits' is not correctly aligned for an int, then
you have undefined behaviour.
I'm unsure of the syntax. I don't need to work in-place so to speak. It is fine to work with a copy.

You can work in-place with:
unsigned int bits32;
and then to access the chars:
((unsigned char *)&bits32)[0]
etc. Note that the contents of the chars could be anything
(eg. big endian, little endian, or something more exotic),
and if you modify one of those chars then you aren't guaranteed
to have anything sensible left in bits32.

If you don't want to work in-place then you could memcpy
between the int and the char (with the same caveats I mentioned
already).

To work portably (assuming a 32-bit int and 8-bit char),
you can use bit-shifts and masks to extract the four bytes
and replace them. A good compiler would optimise this code
into a single instruction, if it could.
Unconsidering the byte sequence, you are correct.
A better way is using a union like:
union xxx
{
unsigned char bits[4];
unsigned int i;
};


Undefined behaviour if you access a member of a union that
wasn't the one you just set.

Jul 23 '05 #6

P: n/a
On 2005-02-17 15:38:50 -0500, "Andrew Koenig" <ar*@acm.org> said:
"MatrixV" <tr******@kcollege.com> wrote in message
news:37*************@individual.net...
Unconsidering the byte sequence, you are correct.
A better way is using a union like:
union xxx
{
unsigned char bits[4];
unsigned int i;
};


Not really. When you use a union, you have no assurance about the
effect that giving a value to one member of a union will have on other
members.


You do when one of them is an array of unsigned char.

--
Clark S. Cox, III
cl*******@gmail.com

Jul 23 '05 #7

P: n/a
Daniel Lidström wrote:
Hello!

I want to work with individual bytes of integers. I know that ints are
32-bit and will always be. Sometimes I want to work with the entire
32-bits, and other times I want to modify just the first 8-bits for
example. For me, I think it would be best if I can declare the 32-bits
like this:

unsigned char bits[4];

When I want to treat this as a 32-bits integer, can I do something
like this?

unsigned int bits32 = *((unsigned int*)bits);

Yes but not like this because array bits is not initialised.
I'm unsure of the syntax. I don't need to work in-place so to speak. It is
fine to work with a copy.

What you can do is read an unsigned int or any other POD type as a
sequence of unsigned chars (or plain chars) - that is bytes, copy it
byte by byte to another unsigned char sequence (which includes possible
padding bits), and deal the new char sequence as another unsigned int.
The following example uses an int and is portable:
#include <iostream>

int main()
{
int integer=0;

unsigned char *puc= reinterpret_cast<unsigned char *>(&integer);
unsigned char otherInt[sizeof(integer)];

// Read integer byte by byte and copy it to otherInt
for(unsigned i=0; i<sizeof(integer); ++i)
otherInt[i]= puc[i];
// We treat the new unsigned char sequence as an int
int *p= reinterpret_cast<int *>(otherInt);

// Assign another value to the integer otherInt!
*p=7;

std::cout<<*p<<"\n";
}


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #8

P: n/a
On Thu, 17 Feb 2005 19:16:24 +0100, Daniel Lidström
<so*****@microsoft.com> wrote in comp.lang.c++:
Hello!

I want to work with individual bytes of integers. I know that ints are
32-bit and will always be.


No, you don't. You just think you do. But you are mistaken.

--
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++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jul 23 '05 #9

P: n/a
>> Not really. When you use a union, you have no assurance about the effect
that giving a value to one member of a union will have on other members.
You do when one of them is an array of unsigned char.


Can you show me where in the C++ standard it says that? The text that I
think is relevant can be found in subclause 9.5:

In a union, at most one of the data members can be active at any time, that
is, the value of at most one of the data members can be stored in a union at
any time. [Note: one special guarantee is made in order to simplify the use
of unions: If a POD-union contains several POD-structs that share a common
initial sequence (9.2), and if an object of this POD-union type contains one
of the POD-structs, it is permitted to inspect the common initial sequence
of any of POD-struct members; see 9.2. ]

I think that "Only one of the data members can be active at any time" is
pretty clear, and the one exception to that rule says nothing about array of
unsigned character.

Jul 23 '05 #10

P: n/a
"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1108680624.856546@athnrd02...
....
What you can do is read an unsigned int or any other POD type as a sequence of unsigned chars (or plain chars) - that is bytes,
copy it byte by byte to another unsigned char sequence (which includes possible padding bits), and deal the new char sequence as
another unsigned int.
The following example uses an int and is portable:
I have to disagree with your "is portable" claim.
Comments inserted below in your code.
#include <iostream>

int main()
{
int integer=0;

unsigned char *puc= reinterpret_cast<unsigned char *>(&integer);
unsigned char otherInt[sizeof(integer)];

// Read integer byte by byte and copy it to otherInt
for(unsigned i=0; i<sizeof(integer); ++i)
otherInt[i]= puc[i];
// We treat the new unsigned char sequence as an int
int *p= reinterpret_cast<int *>(otherInt);
There is no assurance that the attempt to access an int
at the starting address of otherInt will succeed. On some
machines, it could produce an alignment fault.
// Assign another value to the integer otherInt!
*p=7;
The above access could also produce an alignment fault.
std::cout<<*p<<"\n";
}


I think "works on some platforms" versus "can fault on
some platforms" is a good example of "not portable".

--
--Larry Brasfield
email: do***********************@hotmail.com
Above views may belong only to me.
Jul 23 '05 #11

P: n/a
Andrew Koenig wrote:
I think that "Only one of the data members can be active at any time" is
pretty clear, and the one exception to that rule says nothing about array of
unsigned character.


I believfe he is referring to the passage at 3.10 p 15:
If a program attempts to access the stored value of an object through an lvalue of other than one of the following
types the behavior is undefined48):
— the dynamic type of the object,
— a cv-qualified version of the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to the dynamic type of the object,
— a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of
the object,
— an aggregate or union type that includes one of the aforementioned types among its members (including,
recursively, a member of a subaggregate or contained union),
— a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
— a char or unsigned char type.
Jul 23 '05 #12

P: n/a
Andrew Koenig wrote:
Can you show me where in the C++ standard it says that? The text that I
think is relevant can be found in subclause 9.5:

In a union, at most one of the data members can be active at any time, that
is, the value of at most one of the data members can be stored in a union at
any time. [Note: one special guarantee is made in order to simplify the use
of unions: If a POD-union contains several POD-structs that share a common
initial sequence (9.2), and if an object of this POD-union type contains one
of the POD-structs, it is permitted to inspect the common initial sequence
of any of POD-struct members; see 9.2. ]

I think that "Only one of the data members can be active at any time" is
pretty clear, and the one exception to that rule says nothing about array of
unsigned character.

However the interesting part is that the entire union can be read as an
unsigned char/plain char array, as is the case with all POD types.


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #13

P: n/a
Larry Brasfield wrote:
There is no assurance that the attempt to access an int
at the starting address of otherInt will succeed. On some
machines, it could produce an alignment fault. I think "works on some platforms" versus "can fault on
some platforms" is a good example of "not portable".

The standard guarantees that we can both read a POD type as an array of
unsigned chars/plain chars, copy its contents to another array of
unsigned chars/plain chars of the same size, and the new array is an
exact copy of the initial POD object.
That's why you can copy byte by byte or use memcpy() for this, an entire
array of ints for example. The same applies to an individual int.


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #14

P: n/a
Ron Natalie wrote:
Andrew Koenig wrote:
I think that "Only one of the data members can be active at any time" is pretty clear, and the one exception to that rule says nothing about array of unsigned character.
I believfe he is referring to the passage at 3.10 p 15:
If a program attempts to access the stored value of an object through

an lvalue of other than one of the following types the behavior is undefined48):
- the dynamic type of the object,
- a cv-qualified version of the dynamic type of the object,
- a type that is the signed or unsigned type corresponding to the dynamic type of the object, - a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union),
- a type that is a (possibly cv-qualified) base class type of the dynamic type of the object, - a char or unsigned char type.


That passage is irrelevant to this situation. It says
"If (conditions) then the behaviour is undefined". The union
example in question does not meet (conditions). QED.

To put it another way, the passage you quoted doesn't say that
the behaviour is defined for those listed bullet points.

Jul 23 '05 #15

P: n/a
Ron Natalie wrote:
Andrew Koenig wrote:
I think that "Only one of the data members can be active at any time" is pretty clear, and the one exception to that rule says nothing about array of unsigned character.
I believfe he is referring to the passage at 3.10 p 15:
If a program attempts to access the stored value of an object through

an lvalue of other than one of the following types the behavior is undefined48):
- the dynamic type of the object,
- a cv-qualified version of the dynamic type of the object,
- a type that is the signed or unsigned type corresponding to the dynamic type of the object, - a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union),
- a type that is a (possibly cv-qualified) base class type of the dynamic type of the object, - a char or unsigned char type.


That passage is irrelevant to this situation. It says
"If (conditions) then the behaviour is undefined". The union
example in question does not meet (conditions). QED.

To put it another way, the passage you quoted doesn't say that
the behaviour is defined for those listed bullet points.

Jul 23 '05 #16

P: n/a
"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1108771802.327898@athnrd02...
Larry Brasfield wrote:
There is no assurance that the attempt to access an int
at the starting address of otherInt will succeed. On some
machines, it could produce an alignment fault.
I think "works on some platforms" versus "can fault on
some platforms" is a good example of "not portable".

The standard guarantees that we can both read a POD type as an array of unsigned chars/plain chars, copy its contents to another
array of unsigned chars/plain chars of the same size, and the new array is an exact copy of the initial POD object.


True, but irrelevant. Your code had these elements:
unsigned char otherInt[sizeof(integer)];
// ...
// We treat the new unsigned char sequence as an int
int *p= reinterpret_cast<int *>(otherInt);
// Assign another value to the integer otherInt!
*p=7;

Because char may have looser alignment restrictions than
int, the char array named 'otherInt' may start at an address
that is not aligned sufficiently to be a directly accessible int.
The reinterpret_cast can result in a pointer whose value
would never be an int pointer for any normally allocated int.
And therefor the assignment to *p could produce an alignment
fault on some platforms. The MIPS or Alpha are examples.
That's why you can copy byte by byte or use memcpy() for this, an entire array of ints for example. The same applies to an
individual int.


My beef is not with copying an int as a series of bytes. It
is with accessing a whole int at an address not allocated
as an int. That is simply not portable.

--
--Larry Brasfield
email: do***********************@hotmail.com
Above views may belong only to me.
Jul 23 '05 #17

P: n/a
Larry Brasfield wrote:
The standard guarantees that we can both read a POD type as an array of unsigned chars/plain chars, copy its contents to another
array of unsigned chars/plain chars of the same size, and the new array is an exact copy of the initial POD object.

True, but irrelevant. Your code had these elements:
unsigned char otherInt[sizeof(integer)];
// ...
// We treat the new unsigned char sequence as an int
int *p= reinterpret_cast<int *>(otherInt);
// Assign another value to the integer otherInt!
*p=7;

Because char may have looser alignment restrictions than
int, the char array named 'otherInt' may start at an address
that is not aligned sufficiently to be a directly accessible int.

Actually char/unsigned char have no padding bits.

The reinterpret_cast can result in a pointer whose value
would never be an int pointer for any normally allocated int.
And therefor the assignment to *p could produce an alignment
fault on some platforms. The MIPS or Alpha are examples.

I am not sure I understand that. However let me give you another example:
int main()
{
int arrayInt[4]={0};

unsigned char arrayUChar[4 * sizeof(*arrayInt)];
unsigned char *p= reinterpret_cast<unsigned char *>(arrayInt);

// Or memcpy()
for(unsigned i=0; i<4 * sizeof(*arrayInt); ++i)
arrayUChar[i]= p[i];
int *pInt= reinterpret_cast<int *>(arrayUChar);

// Treat p as an exact copy of arrayInt and change the values
// of its ints.
for(unsigned i=0; i< 4 * sizeof(*arrayInt); ++i)
p[i]= i;
}
Isn't this guaranteed to be portable? Take notice of

int *pInt= reinterpret_cast<int *>(arrayUChar);
This is the meaning of an exact copy of a POD type. The same can happen
with a struct for example where I would assign SomeStruct *p instead.
Also here essentially, we access the first int of an int array.

My beef is not with copying an int as a series of bytes. It
is with accessing a whole int at an address not allocated
as an int. That is simply not portable.

We can access an int, because int is a *POD type* and the standard
guarantees that we can create *exact copies* of any POD type and access
them via a pointer or reference of the POD type.

Built in types *are* POD types.


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #18

P: n/a
Ioannis Vranos wrote:
We can access an int, because int is a *POD type* and the standard
guarantees that we can create *exact copies* of any POD type and access
them via a pointer or reference of the POD type.

Built in types *are* POD types.

Actually the standard states:

"2. For any object (other than a base-class subobject) of POD type T,
whether or not the object holds a valid value of type T, the underlying
bytes (1.7) making up the object can be copied into an array of char or
unsigned char.36) If the content of the array of char or unsigned char
is copied back into the object, the object shall subsequently hold its
original value.

[Example:

#define N sizeof(T)

char buf[N];

T obj; // obj initialized to its original value

memcpy(buf, &obj, N); // between these two calls to memcpy,

// obj might be modified
memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar
// type

// holds its original value
—end example]
3. For any POD type T, if two pointers to T point to distinct T objects
obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if
the value of obj1 is copied into obj2, using the memcpy library
function, obj2 shall subsequently hold the same value as obj1. [Example:

T* t1p;
T* t2p;

// provided that t2p points to an initialized object ...
memcpy(t1p, t2p, sizeof(T)); // at this point, every subobject of POD
// type in *t1p contains
// the same value as the corresponding subobject in *t2p
—end example]
4. The object representation of an object of type T is the sequence of N
unsigned char objects taken up by the object of type T, where N equals
sizeof(T). The value representation of an object is the set of bits
that hold the value of type T. For POD types, the value representation
is a set of bits in the object representation that determines a value,
which is one discrete element of an implementation-defined set of values.37)

5. Object types have alignment requirements (3.9.1, 3.9.2). The
alignment of a complete object type is an implementation-defined integer
value representing a number of bytes; an object is allocated at an
address that meets the alignment requirements of its object type."

Unfortunately you are right.
Case 3:

At first the destination must be a pointer of the same object type (and
presumably the allocated space must be for the same type objects.
Secondly, the standard guarantees that only memcpy() works in this case,
and not copying it char by char or unsigned char by unsigned char. In
other words, in an implementation memcpy() can be defined in some exotic
way (e.g. assembly), and still copying it unsigned char by unsigned char
to the destination has undefined behaviour, while using memcpy() for the
same destination is guaranteed to work!
So my examples fixed (and not producing exactly the same results):
#include <iostream>
#include <cstring>

int main()
{
using namespace std;

int integer=4;

int secondInteger;
memcpy(&secondInteger, &integer, sizeof(integer));
cout<<integer<<"\n";
}

and
#include <iostream>
#include <cstring>
int main()
{
using namespace std;

int arrayInt[4]={1,2,3,4};

int secondArrayInt[sizeof(arrayInt)];
memcpy(secondArrayInt, arrayInt, sizeof(arrayInt));

for(unsigned i=0; i< sizeof(4); ++i)
cout<<secondArrayInt[i]<<"\n";
}

Please correct if I am wrong. Aren't the above guaranteed to be portable?

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #19

P: n/a
Ioannis Vranos wrote:
Actually the standard states:

"2. For any object (other than a base-class subobject) of POD type T,
whether or not the object holds a valid value of type T, the underlying
bytes (1.7) making up the object can be copied into an array of char or
unsigned char.36) If the content of the array of char or unsigned char
is copied back into the object, the object shall subsequently hold its
original value.

[Example:

#define N sizeof(T)

char buf[N];

T obj; // obj initialized to its original value

memcpy(buf, &obj, N); // between these two calls to memcpy,

// obj might be modified
memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar
// type

// holds its original value
—end example]
3. For any POD type T, if two pointers to T point to distinct T objects
obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if
the value of obj1 is copied into obj2, using the memcpy library
function, obj2 shall subsequently hold the same value as obj1. [Example:

T* t1p;
T* t2p;

// provided that t2p points to an initialized object ...
memcpy(t1p, t2p, sizeof(T)); // at this point, every subobject of POD
// type in *t1p contains
// the same value as the corresponding subobject in *t2p
—end example]
4. The object representation of an object of type T is the sequence of N
unsigned char objects taken up by the object of type T, where N equals
sizeof(T). The value representation of an object is the set of bits
that hold the value of type T. For POD types, the value representation
is a set of bits in the object representation that determines a value,
which is one discrete element of an implementation-defined set of
values.37)

5. Object types have alignment requirements (3.9.1, 3.9.2). The
alignment of a complete object type is an implementation-defined integer
value representing a number of bytes; an object is allocated at an
address that meets the alignment requirements of its object type."

Unfortunately you are right.
Case 3:

At first the destination must be a pointer of the same object type (and
presumably the allocated space must be for the same type objects.
Secondly, the standard guarantees that only memcpy() works in this case,
and not copying it char by char or unsigned char by unsigned char. In
other words, in an implementation memcpy() can be defined in some exotic
way (e.g. assembly), and still copying it unsigned char by unsigned char
to the destination has undefined behaviour, while using memcpy() for the
same destination is guaranteed to work!
So my examples fixed (and not producing exactly the same results):
#include <iostream>
#include <cstring>

int main()
{
using namespace std;

int integer=4;

int secondInteger;
memcpy(&secondInteger, &integer, sizeof(integer));

cout<<secondInteger<<"\n"; }

and
#include <iostream>
#include <cstring>
int main()
{
using namespace std;

int arrayInt[4]={1,2,3,4};

int secondArrayInt[sizeof(arrayInt)];
memcpy(secondArrayInt, arrayInt, sizeof(arrayInt));

for(unsigned i=0; i< sizeof(4); ++i)
cout<<secondArrayInt[i]<<"\n";
}

Please correct if I am wrong. Aren't the above guaranteed to be portable?


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #20

P: n/a
"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in
message news:1108785342.208655@athnrd02...
Ioannis Vranos wrote:
[Cut many words about validity of byte-wise copying.]

As I mentioned, copying byte by byte is ok in my book.
4. The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T,
where N equals sizeof(T). The value representation of an object is the set of bits
that hold the value of type T. For POD types, the value representation is a set of bits in the object representation that
determines a value, which is one discrete element of an implementation-defined set of values.37)

5. Object types have alignment requirements (3.9.1, 3.9.2). The alignment of a complete object type is an implementation-defined
integer value representing a number of bytes; an object is allocated at an address that meets the alignment requirements of its
object type."

Unfortunately you are right.
Well, I suppose one could look at it that way. However, the
alignment issue arises from machine design decisions that are
made in the interest of cost, complexity and speed. So, to
the extent that having alignment requirements has made some
computers cheaper, more reliable and faster, they might be
regarded as fortunate by the beneficiaries.

Case 3:

At first the destination must be a pointer of the same object type (and presumably the allocated space must be for the same type
objects.
Secondly, the standard guarantees that only memcpy() works in this case, and not copying it char by char or unsigned char by
unsigned char. In other words, in an implementation memcpy() can be defined in some exotic way (e.g. assembly), and still copying
it unsigned char by unsigned char to the destination has undefined behaviour, while using memcpy() for the same destination is
guaranteed to work!
I think file I/O is supposed to work, too. And the language
about value residing in the bytes seems, to me, to guarantee
that any sizeof(T) byte-by-byte copy would preserve value.
So my examples fixed (and not producing exactly the same results):
Please see inserted comments.
#include <iostream>
#include <cstring>

int main()
{
using namespace std;

int integer=4;

int secondInteger;
memcpy(&secondInteger, &integer, sizeof(integer));
cout<<integer<<"\n";
}
Must emit '4' and a line boundary and is portable.
and
#include <iostream>
#include <cstring>
int main()
{
using namespace std;

int arrayInt[4]={1,2,3,4};

int secondArrayInt[sizeof(arrayInt)];
Do you mean to create these 2 arrays the same size?
That is not the effect of the above code.
memcpy(secondArrayInt, arrayInt, sizeof(arrayInt));

for(unsigned i=0; i< sizeof(4); ++i)
cout<<secondArrayInt[i]<<"\n";
}
The sizeof(4) is the same as sizeof(int).

Please correct if I am wrong. Aren't the above guaranteed to be portable?


It will emit a number of integers in text format which
varies according to how many bytes an int occupies.
Not portable by my definition of the term.

--
--Larry Brasfield
email: do***********************@hotmail.com
Above views may belong only to me.
Jul 23 '05 #21

P: n/a
Larry Brasfield wrote:
int secondArrayInt[sizeof(arrayInt)];

Do you mean to create these 2 arrays the same size?
That is not the effect of the above code.

Yes you are right, it should have been 4 or
sizeof(arrayInt)/sizeof(*arrayInt)...


memcpy(secondArrayInt, arrayInt, sizeof(arrayInt));

for(unsigned i=0; i< sizeof(4); ++i)
cout<<secondArrayInt[i]<<"\n";
}

The sizeof(4) is the same as sizeof(int).

Hmm, I was in a hurry and posted non-sense. This was meant to be i<4.
It will emit a number of integers in text format which
varies according to how many bytes an int occupies.
Not portable by my definition of the term.

My non-sense corrected (sorry about that):
#include <iostream>
#include <cstring>

int main()
{
using namespace std;

int integer=4;

int secondInteger;
memcpy(&secondInteger, &integer, sizeof(integer));
cout<<secondInteger<<"\n";
}
and
#include <iostream>
#include <cstring>
int main()
{
using namespace std;

int arrayInt[4]={1,2,3,4};

int secondArrayInt[4];
memcpy(secondArrayInt, arrayInt, sizeof(arrayInt));

for(unsigned i=0; i<4; ++i)
cout<<secondArrayInt[i]<<"\n";
}

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #22

P: n/a
On Thu, 17 Feb 2005 18:22:39 +0000, Andrew Koenig wrote:
"Daniel Lidström" <so*****@microsoft.com> wrote in message
news:pa****************************@microsoft.com. ..
When I want to treat this as a 32-bits integer, can I do something
like this?

unsigned int bits32 = *((unsigned int*)bits);


Yes you can, but you have absolutely no assurance as to what the results
will be :-)

What's wrong with

(bits>>n) & 0xff

where n is 0, 8, 16, or 24?


There is nothing wrong with that, and I think I will use this method.
Except I do it the other way around:

uint8 merge(const uint4 b[2])
{
return (uint8(b[0])<<32) | b[1];
}

Thanks!

--
Daniel

Jul 23 '05 #23

P: n/a
Daniel Lidström wrote:
There is nothing wrong with that, and I think I will use this method.
Except I do it the other way around:

uint8 merge(const uint4 b[2])
{
return (uint8(b[0])<<32) | b[1];
}

Thanks!

Considering it looks like you're trying to merge 2 4-bit integers into 1
8-bit integer, you should be shifting left by 4 not 32.
Jul 23 '05 #24

P: n/a
"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1108771578.265257@athnrd02...
However the interesting part is that the entire union can be read as an
unsigned char/plain char array, as is the case with all POD types.


On the other hand, there's no particular assurance as to its content when
read that way.
Jul 23 '05 #25

P: n/a
Andrew Koenig wrote:
However the interesting part is that the entire union can be read as an
unsigned char/plain char array, as is the case with all POD types.

On the other hand, there's no particular assurance as to its content when
read that way.


Yeap. :-)


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #26

P: n/a
Old Wolf wrote:


That passage is irrelevant to this situation. It says
"If (conditions) then the behaviour is undefined". The union
example in question does not meet (conditions). QED.
The passage doesn't say that. It says OTHER than the listed conditions
the behavior is undefined. Accessing a stored value via an lvalue
of char type IS defined.

To put it another way, the passage you quoted doesn't say that
the behaviour is defined for those listed bullet points.


Yes, but nothing says it's undefined otherwise. The only
prohibition in chapter 9 on unions is that you may only STORE
one value at a time in an union.
Jul 23 '05 #27

P: n/a
Ron Natalie wrote:
Old Wolf wrote:
That passage is irrelevant to this situation. It says
"If (conditions) then the behaviour is undefined". The union
example in question does not meet (conditions). QED.
The passage doesn't say that. It says OTHER than the listed

conditions the behavior is undefined. Accessing a stored value via an lvalue
of char type IS defined.


You used the wrong substitution for (conditions) in my quote.

(conditions) is "a program attempts to access the stored value
of an object through an lvalue of other than one of the following
types".

To put it another way, the passage you quoted doesn't say that
the behaviour is defined for those listed bullet points.


Yes, but nothing says it's undefined otherwise.
The only prohibition in chapter 9 on unions is that you
may only STORE one value at a time in an union.


The quote in question (which you snipped) had nothing to do with
unions and has no bearing on the OP's question.

The suggestion by Clark S Cox was rebuffed by the quote that
Andrew Koenig provided.

Jul 23 '05 #28

This discussion thread is closed

Replies have been disabled for this discussion.