4

In this book I'm reading I'm going over bitwise operators. Its says the following in the book.

Bitwise operations can potentially store a lot of information in a small amount of memory. Many traits in the world have only two possibilities that are either this way or that way. You are either married or you're not. you are either male or female. In C++, you can store each of these traits in a single bit. This way you can pack 32 separte binary properties into a single 32-bit int.

So is what he saying is when you use bitwise operators in C++ it would only cost 1 bit of memory? I'm not sure what the 32-bit int thing is relevent to and also when he talks about "memory" is this the RAM that the program takes up? Because when I run my C++ programs they are way above 1 bits of ram being ocupied. Am I looking at this in the wrong way?

  • 12
    you are either male or female - I'm pretty sure there was a book next to this one that argued that using a single flag for gender is a stupid idea :) – Ordous Jul 21 '16 at 15:19
  • 4
    @Ordous is correct; we do not need to even consider unusual situations such as hermaphrodism to see that a single bit for representing sex is inadequate in many situations. For example, perhaps the sex of the person whose data is being entered in the database is unknown to the person doing the data entry. Rather than trying aggressively to reduce complex quantities to individual bits, instead focus effort on ensuring that data systems accurately reflect the complexity of the world being modeled. – Eric Lippert Jul 21 '16 at 15:25
  • A safer example might be "this integer is divisible by 2", "this integer is divisible by 4", "8", and so on. Lo and behold, as many as 32 such true/false statements can be packed into a single unsigned 32 bit integer! Although of course even then Eric's caveat applies, and you've left yourself no means to indicate that the value of the integer is unknown to the person doing the data entry. – Steve Jessop Jul 21 '16 at 20:51
  • 2
    Honestly, I think the book is not a very good source of information. Apart from what have been mentioned. This statement "Bitwise operations can potentially store a lot of information in a small amount of memory." seems completely vauge and confusing at best, to be (arguably) plain wrong and nonsensical at worst. It suggests like bitwise operations are some magic that can pack more informartion into variable than other operations. Nope. And the amount of information stored in a variable is very precise. It's one bit per bit, of 8 bits per byte. Those are values with precise physical meaning. – luk32 Jul 21 '16 at 21:30
  • 1
    while you may disagree with the categorizations, if you read the assumptions as valid for a fictitious project, then the rest of the explanation makes sense. @luk32 while the storage is "1 bit per bit" the meaning is actually two bits of information, e.g. if the person male or female. And if you use a 2 byte bit field you can store 1 of 4 pieces of information - as long as they are mutually exclusive. – simpleuser Jul 22 '16 at 0:04
15

The book is talking about what is commonly known as bitfields, and their use is often more memory efficient on most platforms, and especially so in serialization or communication contexts. A boolean requires its own address to be usable by the compiler. This means that while, practically, we only need one bit to represent a true (1) or false (0) condition, there is no physical way to address and store one bit in memory. This often means that a boolean will take up an entire byte in memory, just like the smallest integer on that same platform.

Now lets say you had 18 boolean variables. Each one will needs its own addressed piece of memory so that we can reference it elsewhere in the software. That means on our theoretical system we need 18 bytes. People started to see this as a waste of memory, as only one bit out of every byte was really needed.

Enter bitfields. If we look at an integer that matches the system's addressable memory size, we see that it takes up the same number of bits as a single boolean. Integers use all of the bits to represent its range of values. (Decimal value 26 is represented as 00000000 00000000 00000000 00011010 on a 32 bit system, 3572 is 00000000 00000000 00001101 11110100, etc.).

Bitwise operators allow us to play with those bits directly, rather than needing to worry about any real integer value that they were intended to represent. This is important, because if you assign meanings ahead of time to each of those bits, you can set them to 1 and 0 explicitly and treat each bit individually as a boolean.

People love to rip apart analogies but I'm going to give it a shot anyway:

Think of it like a street of houses in a wealthy area full of bachelors. Each home has an address on the street, and each house has 32 rooms, but only one person lives in each house. The bachelors are our booleans. Now lets say a family moves into one of the houses. They are considered one family, but now there are many more people living in the house. This is like our integer - while multiple people are now taking up rooms, we still see it like one house with one value (the family that lives there). Now, another house gets converted to apartments. While its physically still only taking up one house on the street, we assign some letters to each room (Apartment 1A, apartment 2C, etc) that don't affect the physical street address or composition of the house but let us reference each person individually - that's the bit field.

In practice, I'd consider the use of bitfields first instead of booleans as a case of pre-optimization. There are trade-offs in usability; someone else may comment on the trade-offs of speed. Likewise, you can run into issues moving bitfield implementations to different systems if you aren't careful (how would your 32 bit value look on an 8 bit system?) On the flip side, in a small embedded system that I worked on that transferred a ton of status boolean values over a slow serial connection, encoding them as a bitfield was basically a necessity.

  • I really understand now, thanks for the help! I did not really need an analogie but even that explained it further. Many thanks. :) – 99Con Jul 21 '16 at 15:45
  • I think the term refers to &, |, ~, and ^. That would let you explicitly do the kinds of things that you decribe for bit fields, but you don’t use them when using bit fields. – JDługosz Jul 21 '16 at 21:45
4

What is the difference between a normal int and a 32-bit int?

As David Arno points out, you haven't said what you mean by a "normal" int.

So is what he saying is when you use bitwise operators in C++ it would only cost 1 bit of memory?

No, he's saying that if you want to treat integers as collections of bits, you can do so with bitwise operators.

when he talks about "memory" is this the RAM that the program takes up

Begin by no longer thinking of "memory" and "RAM" as the same thing. Memory is the abstract notion of active storage; RAM is just one small part of a complex strategy to reify that abstract notion. Modern memory is, in many ways, better conceived of as pages of a swap file with RAM as the cache.

Next, make your question more crisp. By "the memory that the program takes up" do you mean the memory required to load the program itself into memory, or do you mean the data memory consumed during its execution? If you mean the latter, by "memory" do you mean memory on the temporary pool or the long term storage pool? Each has a different allocation strategy. Managing memory correctly is of vital importance in C++. If you do not understand the difference between short lived and long lived storage, you will write buggy C++ programs. Make sure you understand this difference very clearly.

Am I looking at this in the wrong way?

That seems likely, yes.

  • 1
    "Modern memory is, in many ways, better conceived of as pages of a swap file with RAM as the cache." -- and thus you can see the reason why your program always uses more than 1 bit of memory: memory is allocated (by the operating system) with a granularity that lets it conveniently move it to and from the page file, typically in chunks somewhere between 4KB and 4MB. – Jules Jul 21 '16 at 17:19
  • 1
    It's not accurate to think of RAM as a cache for swap, since, unlike caches, it's perfectly fine to erase a page of swap when it's put into RAM. A cache would preserve the data that it referred to in swap. Modern memory is conceived of as virtual memory as the abstraction, each page of which is actually stored in reality in either RAM or swap. – Olathe Jul 24 '16 at 1:29
2

Your title and question body are asking two different questions.

What is the difference between a normal int and a 32-bit int?

There's no such thing as a "normal" int. The size of int in C++ is platform and compiler dependent.

So is what he saying is when you use bitwise operators in C++ it would only cost 1 bit of memory?

The first thing to note about your quote from the book is the statement "You are either married or you're not. you are either male or female." It highlights a flaw in thinking about either/or traits that can cause problems in code. Both real-world examples are false. In the UK, you could be single, cohabiting, in a civil partnership, married and living together, married and separated, a widow(er) or divorced. There is no "married/ not married"; there are many different relationship states, each with different legal ramifications. Likewise, one may not be either male or female. In addition to the standard XX and XY chromosome pairs, some people are XXX, XXY, XXXX etc and a few people have 49 chromosomes and can be XXXY etc. This leads to complications in determining if someone is eg female in sports, with tests for the Y chromosome having been abandoned as some who identify themselves as female have a Y chromosome. There are many states of maleness and femaleness; it's not a dichotomy.

Likewise in programming, if you start packing data into bits, you can run into situations where you suddenly need a third category (such as when someone in a civil partnership complains that your app only allows for married/not married). Unless you are working on very specialist solutions, memory is cheap and operating on larger data types than bits is often faster.

If you are working on a solution where memory is tight though, and you have lots of state that is truly either/or, then bitwise operations can be used to pack lots of data into a small space. Each flag does indeed only use one bit of memory. Bear in mind though that the compiler will typically allocate 32/64 bits (depending on architecture) to the the value holding your bitwise data, so unless you have a large number of flags, you won't necessarily be saving memory.

Bitwise flags are useful for situations where you have a bunch of complementary options, but their advantage is in the ease of testing them (using bitwise and and or), not in saving memory.

  • "Likewise, one may not be either male or female. In addition to the standard XX and XY chromosome pairs, some people are XXX, XXY, XXXX etc and a few people have 49 chromosomes and can be XXXY etc." -- not to mention the possibility of gender reassignment surgery, etc. – Jules Jul 21 '16 at 17:13
  • @Jules, absolutely. I felt I'd already gone off at quite a tangent though and had to stop somewhere... :) – David Arno Jul 21 '16 at 17:19
  • 1
    married / not married is binary. Each of of 'cohabiting, civil partnership, widow(er), or divorced' are obviously substates of 'not married' (unless the person has remarried, in which case they are 'married'). 'married' means you're married, whether or not, you're living together or separated. – Paulpro Jul 22 '16 at 0:13
  • Additionally, having three or more states doesn't mean you can't use a bit field. You can represent up to 4 states with 2 of the bits and up to 8 states with 3 of the bits in the field. – Paulpro Jul 22 '16 at 0:14
  • @Paulpro. Life isn't that simple, eg due to differing laws in differing countries you can be married in the eye of the law in one country and not married in another. And sure, you can use more than one bit to represent multi-state values, but then it's not bitwise either/or usage. – David Arno Jul 22 '16 at 13:46
1

In C++, an int is at least 16 bits. A long (which I have seen referred to as a 32-bit int) is at least 32 bits.

When you declare and initialize something, like long i = 0, you actually initialize at least 32 bits of memory. If you use bitwise operations, you can access each bit individually.

For example, if you have 32 traits that have two options (meaning they can be encoded in a single bit), you can use a bitmask rather than have 32 separate traits. Of course, this is an optimization for memory usage rather than readability. There are always tradeoffs when doing something like this.

  • I think "at least" needs to be highlighted in this answer... it's too easy to read it incorrectly as "an int is ... 16 bits". – Jules Jul 21 '16 at 17:21
-1

So whenever you initialize a variable with a certain datatype (int, float, long, double, etc.) it preserves a certain number of bits for it in the memory. A basic difference between a 16 and 32-bit floatpoint-number is the range of possible values respectively the count of digits.

Examples: In case of a 16 bit number it is a range from 3,1·10^−5 to 6,6·10^4. A 32-bit number would serve a range from 1,5·10^−45 to 1,5·10−45.

To learn more about Datatypes just visit: Wikipedia: Data Type

I hope this helped a 'bit' ;-)

Mike

protected by gnat Jul 25 '16 at 12:43

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.