10

For my computation I only need to use 7-bit space so I am using a char type. However I wonder if it is possible to declare my own type that uses less than one byte of memory?

Topo
  • 4,783
  • 9
  • 48
  • 70
ElConrado
  • 1,477
  • 4
  • 20
  • 46
  • 7
    WHY?!? The smallest addressable space is a byte so you would still consume an entire byte. – NathanOliver Apr 16 '15 at 19:42
  • 4
    You might be interested in `std::bitset` http://www.cplusplus.com/reference/bitset/bitset/ – brettwhiteman Apr 16 '15 at 19:43
  • @NathanOliver not necessarily, see `std::bitset` - depends how you intend to use it – brettwhiteman Apr 16 '15 at 19:44
  • 3
    Yeah it's possible - only on machines where 1 byte is less than 8 bits (no i'm not joking, these machines really exists) – Chan Kha Vu Apr 16 '15 at 19:45
  • @tux3 including the internal members (such as size and capacity) vector of bool will be much bigger than a byte. – Borgleader Apr 16 '15 at 19:45
  • @Borgleader Well, yeah. You can't really store something smaller than a byte as a single entity. – tux3 Apr 16 '15 at 19:46
  • @Brett but you still have some sort of char/bool implementing the bitset which is size 1 not 1/8 – NathanOliver Apr 16 '15 at 19:48
  • @NathanOliver yeah it depends how you use it - if the OP is intending to store more than 1 bit then he can store multiple within one char – brettwhiteman Apr 16 '15 at 19:49
  • There's not even a builtin type with size smaller than 1, so there's nothing you can base your type on. – molbdnilo Apr 16 '15 at 19:52
  • 2
    Why bother trying to save 1 bit because you only need 7 bits? Any such saving (if it were possible) would likely cause performance issues on an 8-bit machine. – brettwhiteman Apr 16 '15 at 19:56
  • 1
    @Brett no matter what, the amount of memory consumed is going to be `number_of_bits / bits_per_byte + (number_of_bits % bits_per_byte ? 1 : 0)` – NathanOliver Apr 16 '15 at 19:57

5 Answers5

16

Not really. Inside a struct, you can make use of bit fields. So if you know you'll need a certain, fixed amount of entries, this would be a way to save a few bits (but note that the struct will always be padded to at least the next whole amount of bytes). Also note that due to the fact that "normal" CPUs can't address amounts smaller than an octet/byte, the access to these bit field values might be slower because of the extra instructions the compiler has to generate to get/store a value "in the middle". So in order to save a few bits, you have to spend some CPU time.

The C++11 standard says in chapter 1.7 The C++ memory model (emphasis mine):

The fundamental storage unit in the C++ memory model is the byte. A byte is at least large enough to contain any member of the basic execution character set (2.3) and the eight-bit code units of the Unicode UTF-8 encoding form and is composed of a contiguous sequence of bits, the number of which is implementation- defined.

In other words: the smallest addressable unit in C++ is at least 8 bits wide.

Side-note: In case you're wondering: there are machines like DSPs that can only address units larger than 8 bits at a time; for such a machine, the compiler may define "byte" to be, for example, 16 bits wide.

Community
  • 1
  • 1
DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • I don't remember clearly, but I know there is at least one software company that has implemented software-based byte-address support on a word-addressable-only DSP. It'll be interesting to know how they did it, which answer the OP's question. – user3528438 Apr 16 '15 at 20:42
  • @user3528438: I guess they'd implement it almost the same way as one implements bit field support (masking and bit shifting). – DarkDust Apr 16 '15 at 20:52
6

Even if you try to create a bitset with size 1, it will consume a byte. So it is not possible to create a type less than a byte in C++

#include <iostream>       // std::cout
#include <string>         // std::string
#include <bitset>         // std::bitset

int main ()
{
  std::bitset<1> foo;
  std::bitset<1> bar (1);
  std::bitset<1> baz (std::string("1"));

  std::cout << "foo: " << sizeof(foo) << '\n';
  std::cout << "bar: " << sizeof bar << '\n';
  std::cout << "baz: " << sizeof baz << '\n';

  return 0;
}
Steephen
  • 14,645
  • 7
  • 40
  • 47
3

byte is the minimal addressable unit and has the minimum size in C++ equal to 1. And the memory is allocated in bytes. Even an empty class has at least size not less than 1 byte.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    unless you run into [empty base class optimization](http://stackoverflow.com/questions/2826589/empty-base-class-optimization) – NathanOliver Apr 16 '15 at 19:50
2

Assuming the processor isn't some special hardware completely different from regular hardware, you won't gain anything from using 7 instead of 8 bits, since an 8-bit byte is the minimum addressable unit (aside from a few exotic machines that use more than 8 bits to a byte, and in my 30+ years of using computers, I have not worked with one except possibly the Honeywell mainframe that a friend of mine worked during his summer internship which and I was invited to visit for a day - I don't know what model it was, so it may have been a 18- or 36-bit machine - and that was about 1985 or so).

So, assuming you could make a big array of 7-byte "lumps", the compiler would have to generate extra code to extract each 7-byte element from the array, so instead of taking one instruction to fetch one 8-bit byte, all accesses will be at least two operations, and some will straddle two machine-words, requiring two more operations to extract the relevant combination of 7 bits out of the two machine words. It is possible to do, but it would most likely waste more than the 1/8 in space that you waste by using 8-bit words. In other words, even if you COULD do it, there would be a performance drop rather than gain.

It MAY be reasonable if there is a 512-bit word machine, since you could then fit 73 7-bit words into a single 512 bit word. But 512-bit word machines aren't that common, and even the AVX512 instruciton set on x86-64 processors is not really 512-byte word, you can't (easily) access every 7th bit as bitfields, you have to shuffle bits in lumps of 8, 16, 32, 64 etc at a time.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
-1

What would sizeof give for an object smaller than one byte? An integral value between 0 and 1?

sizeof gives the size of its operand in bytes and as 0 is clearly not a possible result, making 1 the smallest possible size since the return type of sizeof is an integral type. Thus no object can have a memory representation less than one byte.

Emil Laine
  • 41,598
  • 9
  • 101
  • 157