17

I was just checking an answer and realized that CHAR_BIT isn't defined by headers as I'd expect, not even by #include <bitset>, on newer GCC.

Do I really have to #include <climits> just to get the "functionality" of CHAR_BIT?

Community
  • 1
  • 1
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • 16
    What's the problem including `climits` or `limits.h`? – Michael Burr Apr 22 '10 at 07:15
  • 4
    It just seems to be a lot of trouble (and potentially compiler time) to avoid writing the magic number 8. – Potatoswatter Apr 22 '10 at 07:36
  • Wait, are you asking for a different way of obtaining the information CHAR_BIT represents? That makes more sense than my initial reading. – Dennis Zickefoose Apr 22 '10 at 07:39
  • 16
    Try meassuring the difference between including that and not, and I bet that you will not notice any difference at all. Remember that *those willing to sacrifice correctness over performance deserve neither*. And we are talking about compilation time, not even runtime. – David Rodríguez - dribeas Apr 22 '10 at 07:42
  • @Dennis: Yes, although I would have been happy if another commonly-used header included ``. – Potatoswatter Apr 22 '10 at 07:43
  • @David: True, but it seems worth asking to see whether a no-sacrifice solution exists. After all, `CHAR_BIT` is a hackish macro just by itself. – Potatoswatter Apr 22 '10 at 07:44

6 Answers6

25

As you may know, whether or not an implementation wants to include other headers is unspecified. It's allowed, but not mandated. (§17.4.4.1) So you either have to be explicit or know your guarantees.

The only time a C++ header must include another is if it requires a definition in another. For example, <bitset> is required to include <cstddef> for std::size_t, as this is explicitly stated in the standard. (§23.3.5, for this example)

For a counter-example, consider <limits>. It may include <climits> and define the values for numeric_limits in terms of the macros within, and it often does since that's easiest for an implementation. But all the standard says is things like: "Equivalent to CHAR_MIN, SHRT_MIN, FLT_MIN, DBL_MIN, etc." but doesn't say it must to be implemented in terms of those, which means <climits> doesn't have to be included.

So the only way you can be guaranteed that a CHAR_BIT is defined is by including <climits> or some other header where it's explicitly stated it must include it. And as far as I can tell, none have to; an implementation is free to just hard-code the value everywhere it's needed, for example, or include <limits> and use std::numeric_limits<unsigned char>::digits (which is equivalent).

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • 3
    You even answered the question in the title, and provided a better name for it! – Potatoswatter Apr 22 '10 at 07:40
  • 4
    Mostly unimportant trivia: Note that an implementation including other standard headers is allowed only for C++. In C, a compiler implementation is only permitted to define `CHAR_BIT` if `limits.h` is included. In fact, if `limits.h` isn't included by the user, it's perfectly OK (by the C standard) for the user to define `CHAR_BIT` himself for his own use - that identifier is only reserved if `limits.h` is included. Not that I'd advocate that as a good idea, but it's OK as far as the C standard is concerned. – Michael Burr Apr 22 '10 at 18:07
  • 8
    Important trivia: `numeric_limits::digits` is equivalent to `CHAR_BIT` only if `char` is unsigned. If `char` is signed, then it's equivalent to `(CHAR_BIT - 1)`, since the `digits` member doesn't count the sign bit. I'd just go ahead and `#include ` to get the number you want. – Michael Burr Apr 22 '10 at 18:10
  • @Michael: You can do `unsigned char` like in the answer for the equivalent, too. – GManNickG Apr 22 '10 at 18:38
  • 1
    @GMan: I just wanted to specifically call out that you have to take care to use `unsigned char` and not just `char`. – Michael Burr Apr 22 '10 at 19:09
  • 1
    @Michael: Ah, gotcha. :) One could also do `numeric_limits::digits + numeric_limits::is_signed`, but meh. – GManNickG Apr 22 '10 at 19:29
9

Unless you're programming for DSPs, a better name for it is 8. POSIX and Windows both require CHAR_BIT==8, and that covers pretty much every interesting target conceivable except DSPs. (I would not consider 1970s mainframes a potentially interesting target anymore, but perhaps someone will beg to differ...)

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 2
    True nuff, but in a possibly complicated formula for calculating the size of a `std::bitset`, I'll be avoiding literal numbers like the plague. – Potatoswatter Sep 06 '11 at 00:16
6

<climits> is where CHAR_BIT is required to be by the C++ standard. Even if you happened to find it in <bitset>, its not guaranteed to be there, so you're better off going straight to the source. Its not like there's something wrong with including <climits>.

Dennis Zickefoose
  • 10,791
  • 3
  • 29
  • 38
3

Define "newer". A random Linux system gave me these results:

~> gcc --version
gcc (GCC) 4.1.2 (Gentoo 4.1.2)
[snip]

~> grep CHAR_BIT /usr/include/*.h
/usr/include/limits.h:#  define CHAR_BIT        8

Doesn't that qualify? In C, I think it should always be enough to include limits.h to get CHAR_BIT.

unwind
  • 391,730
  • 64
  • 469
  • 606
0

Yes, you should #include <limits.h> to get the definition of CHAR_BIT. It's not a bottleneck at all for your program (see comment below), and later down the line you might find yourself porting to different platforms. Not every implementation has the value of 8

Xavier Ho
  • 17,011
  • 9
  • 48
  • 52
0

I keep the following function in my .profile to check compiler defined constants. On my system __CHAR_BIT__ is in there, which means no header is required if you can live with the double underscore form, which may only work with gcc.

defines () 
{ 
    touch /tmp/defines.h;
    cpp -dD "$@" /tmp/defines.h | awk '$1!="#"{COUNT+=1;print;}END{printf("count %d\n",COUNT);}' | sort;
    rm /tmp/defines.h
}
drawnonward
  • 53,459
  • 16
  • 107
  • 112
  • 7
    So you've got a platform-specific workaround to avoid including a header that was only required in order to avoid making assumptions about the platform in the first place? – jalf May 09 '10 at 00:04
  • It answers the question. Is gcc a platform? – drawnonward May 09 '10 at 02:21