Home > OS >  Fixed point arithmetic long long int representation issue in C
Fixed point arithmetic long long int representation issue in C

Time:08-24

I am struggling with the realization of a signed long long int variable having the value 1 set in its integer part. Looking at the 16.16 implementation with a signed long int variable it does work like this:

static signed long int varInit = 1 << 16; /* alternatively: 65536 */
unsigned short int integer_part,fractional_part;
fractional_part = ((unsigned short int *) &varInit)[0];
integer_part = ((unsigned short int *) &varInit)[1];

This leads to the following representation: 0001.0000

Unfortunately I cannot get it to work in the 32.32 representation:

static signed long long int varInit = 1 << 32;
unsigned long int integer_part,fractional_part;
fractional_part = ((unsigned long int *) &varInit)[0];
integer_part = ((unsigned long int *) &varInit)[1];

I get the following gcc warning: warning: left shift count >= width of type

What am I getting wrong?

I am trying to get the following representation: 00000001.00000000

CodePudding user response:

This expression

1 << 32

has undefined behavior because the operands have the type int and the result also has the type int.

From the C Standard (6.5.7 Bitwise shift operators)

3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined

At least use the expression

1LL << 32

CodePudding user response:

I am trying to get the following representation: 00000001.00000000 (hexadecimal).

Do not use int, long, long long as their widths vary from platform to platform. Use (u)int32_t, (u)int64_t for consistency.

1 << 32 is int math - often too narrow for shifting 32 bits. To form the binary value 1_00000000_00000000_00000000_00000000, use (u)int64_t math.

Do not assume byte layout of wide integer types with code like fractional_part = ((unsigned short int *) &varInit)[0];. Use math and let the compiler emit optimal code.


#include <stdint.h>

static int64_t varInit = ((int64_t)1) << 32;
// or 
static int64_t varInit = INT64_C(1) << 32;

int32_t integer_part = varInit >> 32;
uint32_t fractional_part = varInit & 0xFFFFFFFFu;
// or 
int32_t integer_part = varInit / 0x100000000;
uint32_t fractional_part = varInit % 0x100000000u;
 
  • Related