Wednesday, February 18, 2015

Digest for comp.lang.c++@googlegroups.com - 6 updates in 2 topics

Greg Martin <greg.at.softsprocket@dot.com>: Feb 18 02:53PM


> Bit-fields cannot be accessed except as part of their containing struct.
> In particular, you cannot take the address of a bitfield (§6.5.3.2 of
> N1570, if you want chapter and verse).
 
Ah, but if it walks like a duck and talks like a duck is it a duck?
note: I can't think of a single reason why you'd do this.
 
 
////////////////////////////////////////////////////////////////////////
#include <iostream>
 
class uint8 {
friend std::ostream& operator<< (std::ostream& out, uint8& ui);
private:
struct {
unsigned char d : 8;
};
public:
uint8 (const unsigned int i) : d(i) {}
uint8 () : d(0) {}
uint8 (const uint8& o) : d(o.d) {}
uint8 (uint8&& o) : d(o.d) { o.d = 0; }
~uint8 () {}
 
uint8& operator= (const uint8& o) {
d = o.d;
return *this;
}
 
uint8& operator= (uint8&& o) {
d = o.d;
o.d = 0;
return *this;
}
 
uint8& operator= (const unsigned int i) {
d = i;
return *this;
}
 
bool operator== (const unsigned int i) {
return d == i;
}
 
bool operator== (const uint8& o) {
return d == o.d;
}
 
};
 
std::ostream& operator<< (std::ostream& out, uint8& ui) {
out << (unsigned int) ui.d;
return out;
}
 
int main () {
uint8 u8 = 255;
 
std::cout << u8 << "\n";
std::cout << (u8 == 255) << "\n";
 
uint8 u8_2 = u8 = 0xFFFE;
 
std::cout << u8 << "\n";
std::cout << (u8 == 255) << "\n";
std::cout << (u8 == u8_2) << "\n";
 
std::cout << sizeof u8 << "\n";
 
uint8* pu8 = &u8;
 
std::cout << *pu8 << "\n";
 
return 0;
}
 
 
--
http://www.softsprocket.com
David Brown <david.brown@hesbynett.no>: Feb 18 04:48PM +0100

On 18/02/15 15:53, Greg Martin wrote:
>> In particular, you cannot take the address of a bitfield (§6.5.3.2 of
>> N1570, if you want chapter and verse).
 
> Ah, but if it walks like a duck and talks like a duck is it a duck?
 
Some languages (such as Python) have duck-typing, but C++ does not
(although templates come close, I suppose).
 
So no, this is not a duck - if you have a system with a 16-bit char,
then your uint8_t class would take 1 char, or 16 bits, of space, and
you'd lose the size and alignment requirements of a real uint8_t.
 
> note: I can't think of a single reason why you'd do this.
 
Actually, I can think of /two/ reasons why you might want something
similar, with a simple "unsigned char" for "d" rather than a bitfield.
 
While a single sort_of_uint8 on a 16-bit char system would not save much
space, you could use it with a specialised std::array template to let
you pack 8-bit items into an array taking half the space of a normal
"unsigned char" array. It wouldn't have all the features correct (you
couldn't take a reference to or address of elements), but it could still
be useful.
 
And on 8-bit processors (such as the AVR), wrapping a uint8_t inside a
class like this can lead to better code than using a plain uint8_t,
because in many situations a plain uint8_t gets "integer promotion" to
16-bit (and thus takes twice the number of instructions), while the
class version does not.
 
 
 
<snip implementation>
scott@slp53.sl.home (Scott Lurndal): Feb 18 04:18PM

>"unsigned char" array. It wouldn't have all the features correct (you
>couldn't take a reference to or address of elements), but it could still
>be useful.
 
Not unlike the Burroughs large systems, where with a 48-bit addressible
object size, character data was generally packed 6 (EBCDIC) or 8 (6-bit BCD)
characters per word. I'm pretty sure there's an extant C compiler for
this architecture.
 
This was also commonly used on the PDP-8 (12-bit words) to pack two 6-bit
characters into a single memory word (subtracting 64 from character values
greater than 64 (or clearing bit[6])).
 
radix-50 encoding was used on the 18/36-bit word-sized PDP systems to pack
characters into a word and was also used on the PDP-11.
Paavo Helde <myfirstname@osa.pri.ee>: Feb 18 12:58PM -0600

David Brown <david.brown@hesbynett.no> wrote in
> are part of a union. This is why classes without data members (or
> virtual functions) have size 1 rather than size 0 - the different
> addresses allow them to be distinguished.
 
Objects of different types can have the same address. This is common for
the most derived object and its first base class subobject, for example.
And that's why empty base class optimization is possible.
 
The main meaning of sizeof() is to define element spacing when things are
put in an array. One cannot put bitfields or incomplete objects in an
array, so sizeof() does not apply for them.
 
Cheers
Paavo
"Lőrinczy Zsigmond" <zsiga@nospam.for.me>: Feb 18 09:28AM +0100

Sorry for the bugs... A more complete version is here:
http://web.axelero.hu/lzsiga/ram.cc
 
example output:
 
constructor#1: user_data=1
constructor#2: copy source=#1, user_data=1
I am instance #2, user_data=1
 
constructor#3: user_data=2
user_data(operator=) to=#2, from=#3, user_data=2
I am instance #2, user_data=2
Martijn Lievaart <m@rtij.nl.invlalid>: Feb 18 03:40PM +0100

On Wed, 18 Feb 2015 14:03:10 +0000, Stefan Ram wrote:
 
 
> can be thought of as a field-by-field copy (at least in the simple
> case of POD-like objects) from object1 to object0 that does not change
> the existence status of object0 or object1.
 
Correct, that is operator=() in action.
 
M4
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: