Should I use stdint.h integer types on 32/64 bit machines?

One thing that worries me about regular integer c declarations is that their names are weird, "long long" is the worst. I'm only building for 32 and 64 bit machines, so I don't necessarily need the portability offered by the library, however I like that the name for each type is one word of the same length without ambiguity in size.

// multiple word types are hard to read
// long integers can be 32 or 64 bits depending on the machine

unsigned long int foo = 64;
long int bar = -64;

// easy to read
// no ambiguity

uint64_t foo = 64;
int64_t bar = -64;

      

On 32-bit and 64-bit machines:

1) Can a smaller integer like int16_t be used slower than something larger like int32_t?

2) If I need a for loop to run just 10 times, can I use the smallest integer that can handle it instead of a typical 32-bit integer?

for (int8_t i = 0; i < 10; i++) {

}

      

3) Whenever I use an integer that I know will never be negative, would it prefer to use the unsigned version, even though I don't need the extra range in the parameters?

// instead of the one above
for (uint8_t i = 0; i < 10; i++) {

}

      

4) Is it possible to use typedef for the types included in stdint.h

typedef int32_t signed_32_int;
typedef uint32_t unsigned_32_int;

      

edit: both answers were equally good and I couldn't actually lean towards one, so I just picked the responder with less rep

+3


source to share


3 answers


1) Can a smaller integer like int16_t be used slower than something larger like int32_t?

Yes, it might be slower. Use instead int_fast16_t

. Profile your code as needed. Performance is highly implementation dependent. The main advantage int16_t

is its small, well-defined size (it should also be 2's complement), as used in structures and arrays, not for speed.

The typedef name int_fastN_t

denotes the highest type of integer sign with a width of at least N. C11 Β§7.20.1.3 2




2) If I need a for loop to run just 10 times, can I use the smallest integer that can handle it instead of a typical 32-bit integer?

Yes, but the savings in code and speed are questionable. Suggest instead int

. The emitted code tends to be speed / size optimal with the native size int

.




3) Whenever I use an integer that I know will never be negative, is it okay to use the unsigned version, even if I don't need the extra range in the parameters?

Using some unsigned type is preferred when the math is strictly unsigned (like indexing an array with size_t

), but the code has to look at a sloppy application like

for (unsigned i = 10 ; i >= 0; i--) // infinite loop

      




4) Is it possible to use typedef for the types included in stdint.h

Almost always. Types such as int16_t

are optional. Maximum portability uses required types uint_least16_t

and uint_fast16_t

to run code on rare platforms using bit widths like 9, 18, etc.

+3


source


Could using a smaller integer like int16_t be slower than using something larger like int32_t?

Yes. Some processors do not have dedicated 16-bit arithmetic instructions; arithmetic on 16-bit integers must be emulated with a sequence of commands line by line:

r1 = r2 + r3
r1 = r1 & 0xffff

      

The same principle applies to 8-bit types.

Use "fast" integer types <stdint.h>

to avoid this, for example int_fast16_t

will give you an integer that is at least 16 bits wide, but can be wider if the 16 bit types are not optimal.

If I needed a for loop to run just 10 times, could I use the smallest integer that can handle it instead of the typical 32-bit integer?

Do not worry; just use int

. Using a narrower type doesn't actually save any space and can cause line-by-line problems if you decide to increase the iteration count to 127 and forget that the loop variable is using the narrow type.



Whenever I use an integer that I know will never be negative, is it okay to use the unsigned version, even if I don't need the extra range?

Best avoided. Some C idioms do not work as expected on unsigned integers; for example, you cannot write a form loop:

for (i = 100; i >= 0; i--) { … }

      

if i

is an unsigned type because it i >= 0

will always be true!

Is it possible to use a typedef for types included in stdint.h

Safe from a technical point of view, but annoying for other developers who need to work with your code.

Use names <stdint.h>

. They are standardized and fairly easy to print.

+3


source


  • Absolutely possible, yes. On my laptop (Intel Haswell), in a micro-object that counts up and down between 0 and 65535 on two registers 2 billion times, it takes

    1.313660150s - ax dx (16-bit)
    1.312484805s - eax edx (32-bit)
    1.312270238s - rax rdx (64-bit)
    
          

    Cons but recurring timing differences. (I wrote a test in assembly because C compilers can optimize it to a different register size.)

  • It will work, but you will need to update it if you change the bounds, and the C compiler will probably optimize it to the same assembly code.

  • As long as it is correct C, it is perfectly normal. Be aware that unsigned overflow is defined and signature overflow is undefined, and compilers use this for optimization. For example,

    void foo(int start, int count) {
        for (int i = start; i < start + count; i++) {
            // With unsigned arithmetic, this will execute 0 times if
            // "start + count" overflows to a number smaller than "start".
            // With signed arithmetic, that may happen, or the compiler
            // may assume this loop always runs "count" times.
            // For defined behavior, avoid signed overflow.
        }
    
          

  • Yes. In addition, POSIX provides inttypes.h

    , which extends stdint.h

    with some useful functions and macros.

+1


source







All Articles