Guaranteeing data type size

110 Views Asked by At

Is there a correct or conventional way to guarantee a data type will be sizeof 4?

Previously I had just done some typedef statements based upon sizeof different data types, and I was wondering if there is a better or more conventional method to have data types of a pre determined size on different architectures?

For the sake of this question lets say I have a large array of chars that I have read from a file. I want to read a series of 24 bit Integers from this char array. In the past I have casted the array to a data type with a sizeof my desired data type, this method fails however if there is no primitive data type with my desired size.

What is the best way to handle this situation?

  char x[10] = {1,1,1,1,1,1,1,1,1,1};
  uint32_t* y = (uint32_t*)x;
  for(int i=0; i < 10; i++)std::cout << "y: " << y[i] << "\n";

  output:
  y: 16843009
  y: 16843009
  y: 257

  desired output:
  y: 65793
  y: 65793
  y: 65793
   ....
2

There are 2 best solutions below

0
On

Go old school and read-a-byte, read-a-byte, read-a-byte-byte-byte!

uint32_t read24(unsigned char *& bufp)
{
    uint32_t val;
    val = *bufp++;
    val |= *bufp++ << 8;
    val |= *bufp++ << 16;
    return val;
}

Usage:

unsigned char buffer[] = 
{ 0x2A, 0x00, 0x00, 0x9A, 0x02, 0x00, 0x4E, 0x61, 0xBC };
unsigned char * bufp = buffer;
uint32_t A = read24(bufp);
uint32_t B = read24(bufp);
uint32_t C = read24(bufp);

Why unsigned chars? Easiest way to deal with sign extension. If you use signed chars, you have to do masking like this:

val = *bufp++ & 0xFF;

to strip off the extra sign bits.

And watch out for endian. Depending on where your data is coming from you might have to read everything in the other direction.

0
On

The fixed-width type uint32_t is designed for this. It will be constructed from whatever primitive is appropriate on your system.

You can find it in <cstdint> or, pre-C++11, in Boost as <boost/cstdint.hpp>. C also provides a` that may be of use.

Failing that, char[4]?