Bitfields?? "shift too large" in initialziation list.

M

MikeWhy

Why shouldn't the following work? VC2008 complains "shift count negative or
too big, undefined behavior". Indeed, foo.b and foo.c contain 0, given
non-zero values.

The following prints:
8
162e (5678:0:0)
162f (5679:0:0)
cd2000000000162e (5678:1234:1)

//=====================================
// fooBitfield.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


typedef unsigned __int64 Unt64;
struct Foo
{
//=============
Unt64 a : 52;
Unt64 b : 11;
Unt64 c : 1;
};

std::eek:stream & operator<<(std::eek:stream & os, const Foo & r)
{
const Unt64 ival = *reinterpret_cast<const Unt64*>(&r);
os << std::hex << ival << std::dec << " ("
<< r.a << ':'
<< r.b << ':'
<< r.c << ')';
return os;
}
int main(int argc, char** argv)
{
//-- doesn't work. Prints "(5678:0:0)"
{
const Foo foo = {
(Unt64)atoi(argv[1]),
(Unt64)atoi(argv[2]),
(Unt64)atoi(argv[3])
};
std::cout << sizeof(foo) << '\n'
<< foo << '\n';
}

//-- doesn't work. Prints "(5679:0:0)"
{
//!! const Foo foo2 = { 3, 3, 3};
const Foo foo2 = { 3ULL, 3ULL, 3ULL }; // makes no difference.
std::cout << foo2 << '\n';
}

//-- works just fine.
{
Foo foo3;
foo3.a = atoi(argv[1]);
foo3.b = atoi(argv[2]);
foo3.c = atoi(argv[3]);
std::cout << foo3 << '\n';
}

return 0;
}
 
Z

ZMZ

I tried in VC 2008 SP1 (32 bits),

//-- doesn't work. Prints "(5679:0:0)"
{
//!! const Foo foo2 = { 3, 3, 3};
const Foo foo2 = { 3ULL, 3ULL, 3ULL }; // makes no difference.
std::cout << foo2 << '\n';
}

It prints out (3:0:0) for me, instead of 5679:0:0.

It is probably a bug in VC. I tried the code (change _int64 to long
long) in GCC and it works fine.

Btw, in VC, if you make the bit field size smaller (smaller than 32
bits), everything within 32bits will work just fine too, only those
fields exceeding 32bits will have problem.
 
I

Ian Collins

Why shouldn't the following work? VC2008 complains "shift count negative
or too big, undefined behavior". Indeed, foo.b and foo.c contain 0,
given non-zero values.

The following prints:
8
162e (5678:0:0)
162f (5679:0:0)
cd2000000000162e (5678:1234:1)

typedef unsigned __int64 Unt64;
struct Foo
{
//=============
Unt64 a : 52;
Unt64 b : 11;
Unt64 c : 1;
};

long long isn't officially supported (yet) in C++, so how the compiler
handles long long bit fields is an implementation specific issue. Some
will refuse to compile them (Sun CC will in 32 bit mode).

You have probably hit a compiler bug.

Incidentally, Sun CC gets it wrong:

8
80b0000000000034 (52:11:1)
300000003 (12884901891:0:0)
80b0000000000034 (52:11:1)

gcc gets it right:

8
80b0000000000034 (52:11:1)
8030000000000003 (3:3:1)
80b0000000000034 (52:11:1)

and warns about 3 not fitting in a single bit.
 
M

MikeWhy

Pete Becker said:
long long isn't officially supported (yet) in C++, so how the compiler
handles long long bit fields is an implementation specific issue. Some
will refuse to compile them (Sun CC will in 32 bit mode).

The layout of bit-fields is always implementation-specific:

Allocation of bit-fields within a class object is implementation-defined.
Alignment of bit-fields is
implementation-defined. Bit-fields are packed into some addressable
allocation unit.
[ Note: bit-fields straddle allocation units on some machines and not on
others. Bit-fields
are assigned right-to-left on some machines, left-to-right on others. —
end note ]

9.6 [class.bit] /1

Thanks, one and all. It was all very helpful.
 
B

Balog Pal

ZMZ said:
I tried in VC 2008 SP1 (32 bits),
//-- doesn't work. Prints "(5679:0:0)"
{
//!! const Foo foo2 = { 3, 3, 3};
const Foo foo2 = { 3ULL, 3ULL, 3ULL }; // makes no difference.
std::cout << foo2 << '\n';
}

It prints out (3:0:0) for me, instead of 5679:0:0.

One field has only 1 bits and gets assigned value of 3. I'd bet that is
undefined behavior, so anything can happen. Does it work without overflow?
 
Z

ZMZ

One field has only 1 bits and gets assigned value of 3. I'd bet that is
undefined behavior, so anything can happen. Does it work without overflow?

No, not working.

For VC, as long as you have bit fields beyond 32bits, regardless the
number of bits and the value used to initialize it, the result will be
wrong.
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top