JBravo
JBravo

Reputation: 41

Using Int (32 bits) over char (8 bits) to 'help' processor

In C, often we use char for small number representations. However Processor always uses Int( or 32 bit) values for read from(or fetch from) registers. So every time we need to use a char or 8 bits in our program processor need to fetch 32 bits from regsiter and 'parse' 8 bits out of it. Hence does it sense to use Int more often in place of char if memory is not the limitation? Will it 'help' processor?

Upvotes: 3

Views: 448

Answers (4)

simonzack
simonzack

Reputation: 20928

There's the compiler part and the cpu part.

If you tell the compiler you're using a char instead of an int, during static analysis it will know the bounds of the variable is between 0-255 instead of 0-(2^32-1). This will allow it to optimize your program better.

On the cpu side, your assumption isn't always correct. Take x86 as an example, it has registers eax and al for 32 bit and 8 bit register access. If you want to use chars only, using al is sufficient. There is no performance loss.

I did some simple benchmarks in response to below comments:

al:

format PE GUI 4.0

xor ecx, ecx
dec ecx
loop_start:
inc al
add al, al
dec al
dec al
loopd short loop_start
ret

eax:

format PE GUI 4.0

xor ecx, ecx
dec ecx
loop_start:
inc eax
add eax, eax
dec eax
dec eax
loopd short loop_start
ret

times:

$ time ./test_al.exe 
./test_al.exe  0.01s user 0.00s system 0% cpu 7.102 total
$ time ./test_eax.exe 
./test_eax.exe  0.01s user 0.01s system 0% cpu 7.120 total

So in this case, al is slightly faster, but sometimes eax came out faster. The difference is really negligible. But cpus aren't so simple, there might be code alignment issues, caches, and other things going on, so it's best to benchmark your own code to see if there's any performance improvement. But imo, if your code is not super tight, it's best to trust the compiler to optimize things.

Upvotes: 3

bare_metal
bare_metal

Reputation: 1194

From ARM system developers guide

"most ARM data processing operations are 32-bit only. For this reason, you should use a 32-bit datatype, int or long, for local variables wherever possible. Avoid using char and short as local variable types, even if you are manipulating an 8- or 16-bit value"

an example code from the book to prove the point. note the wrap around handling for char as opposed to unsigned int.

int checksum_v1(int *data)
{
char i;
int sum = 0;
for (i = 0; i < 64; i++)
{
sum += data[i];
}
return sum;
}

ARM7 assembly when using i as a char

checksum_v1
MOV r2,r0 ; r2 = data
MOV r0,#0 ; sum = 0
MOV r1,#0 ; i = 0
checksum_v1_loop
LDR r3,[r2,r1,LSL #2] ; r3 = data[i]
ADD r1,r1,#1 ; r1 = i+1
AND r1,r1,#0xff ; i = (char)r1
CMP r1,#0x40 ; compare i, 64
ADD r0,r3,r0 ; sum += r3
BCC checksum_v1_loop ; if (i<64) loop
MOV pc,r14 ; return sum

ARM7 assembly when i is an unsigned int.

checksum_v2
MOV r2,r0 ; r2 = data
MOV r0,#0 ; sum = 0
MOV r1,#0 ; i = 0
checksum_v2_loop
LDR r3,[r2,r1,LSL #2] ; r3 = data[i]
ADD r1,r1,#1 ; r1++
CMP r1,#0x40 ; compare i, 64
ADD r0,r3,r0 ; sum += r3
BCC checksum_v2_loop ; if (i<64) goto loop
MOV pc,r14 ; return sum

Upvotes: 1

Michał G&#243;rny
Michał G&#243;rny

Reputation: 19233

If your program is simple enough, the optimizer can do the right thing without you having to worry about it. In this case, plain int would be the simplest (and forward-proof) solution.

However, if you want really much to combine specific bit width and speed, you can use 7.18.1.3 Fastest minimum-width integer types from the C99 standard (requires C99-compliant compiler).

For example:

int_fast8_t x;
uint_fast8_t y;

are the signed and unsigned types that are guaranteed to be able to store at least 8 bits of data and use the usually faster underlying type. Of course, it all depends on what you are doing with the data afterwards.

For example, on all systems I have tested (see: standard type sizes in C++) the fast types were 8-bit long.

Upvotes: 1

Bathsheba
Bathsheba

Reputation: 234665

I'd stick to int if I were you as that is probably the most native integral type for your platform. Internally you could expect shorter types to be converted to int so actually degrading performance.

You should never use char and expect it to be consistent across platforms. Although the C standard defines sizeof(char) to be 1, char itself could be signed or unsigned. The choice is down to the compiler.

If you believe that you can squeeze some performance gain in using an 8 bit type then be explicit and use signed char or unsigned char.

Upvotes: 2

Related Questions