Pros/cons to using char for small integers in C
Is there any disadvantage to using char
for small integers in C? Are there any advantages other than the occupancy/memory benefit?
In particular, is the processor likely to cope with integer arithmetic on a char
better or worse than it would on a (long
/short
) int
?
I kn开发者_运维百科ow this will be processor/system/compiler specific, but I'm hoping for an answer in the general case, or, at least, the general case for 32-bit Windows and Solaris, being the systems I'm currently working on. I'm also assuming that things like overflow/wraparound issues have already been dealt with.
Update: Visual Studio 6.0 doesn't actually have stdint.h
as suggested by Christoph. A little benchmarking on Windows (VS 6.0, debug build, 32-bit) with a handful of stacked loops gives int
and long
as providing similar performance, which is about twice as fast as char
. Running the same test on Linux with gcc similarly pegs int
and long
as similar, and both faster than char
, although the difference is less pronounced.
As a side note, I've not spent much time looking, but the first implementation of stdint.h
for VS 6.0 I found (via Wikipedia) defines uint_fast8_t
as unsigned char
, despite this seeming to be slower in my tests at least. Thus, the moral of the story, as Christoph rightly suggested: always benchmark!
C99 added so-called 'fastest' minimum-width integer types to solve this problem. For the range you're interested in, the types would be int_fast8_t
and uint_fast8_t
, which can be found in stdint.h
.
Keep in mind that there might be no performance gain (the increase in memory consumption might even slow things down); as always, benchmark! Don't optimize prematurely or solely on potentially flawed assumptions of what should work.
Well, the first issue is that it's not defined by the C standard whether plain char
is signed or unsigned - so the only range you can portably rely on is 0 to 127.
Other than that, in general int
is supposed to be the type corresponding to the native word size of the architecture (but of course this isn't enforced by anything). This would tend to be the type with the best arithmetic performance, but that's about all you can say.
Note that operands narrower than int
are widened either to int
or unsigned int
during expression evaluation anyway.
Another con I can think of is that (as far as I know) "modern" processors do all their math in "full" integers, generally 32 bits. So dealing with a char
usually means pulling a single byte out of memory, filling up with 0's in transferring to a register, doing something with it and then squeezing only the least significant bits of the result back into memory. Especially if the char
is not aligned on a handy boundary, this memory access takes a lot more work to accomplish.
Using char
for int
is really only useful when you have a lot of numbers (i.e. a large array) and you need to conserve space.
Arithmetic on chars will almost certainly actually performed using the same registers as arithmetic on ints. For example:
char c1 = 1;
char c2 = c1 + 2;
The addition compiles to the following with VC++:
00401030 movsx eax,byte ptr [ebp-4]
00401034 add eax,2
00401037 mov byte ptr [ebp-0Ch],al
where eax is a 32-bit register.
There is therefore no adavantage for using chars over ints when it comes to arithmetic performance.
Internally, processors generally perform arithmetic on machine words. This means that when calculations on other types are performed, although the calculation itself will take the same length of time, depending on the available instruction set extra work may have to be done to read inputs and to coerce calculation results into the target type (e.g. sign-extending/zero-filling, shifting/masking to avoid unaligned memory accesses, etc).
This is why C defines types and operations as it does - the size of int
is not mandated by the standard, allowing compiler authors to make it correspond to a machine word, and expression evaluation is defined to promote smaller integer types to int
, greatly reducing the number of points at which results must be coerced to some target type.
Valid reasons to use char
for storing integer values are when the space really matters that much (not as often as you might think), and when describing some external data format / protocol that you are marshalling data to / from. Expect uses of char
to incur a slight loss of performance, especially on hardware such as Cell SPU where only machine word size memory accesses are available so accessing a char in memory requires several shifts and masks.
The main con I would see is that your code is using a type that means one thing for values that mean something else -- e.g., there's a semantic problem which could be a maintenance problem. If you did it, I'd probably recommend typedefing it:
typedef char REALLYSHORT;
That way, A) It's clearer what you're doing, and B) You can change it easily (e.g., just the one place) if you run into trouble.
Do you have a really good reason not to use int
?
精彩评论