Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a 32 bit signed integer value to 64 bit signed integer equivalent in C

Tags:

c++

c

casting

I have a library that is compiled to use 32 bit signed integer. When other applications compile theirs with a flag e.g: -DODBC64 it promotes the same type I have used in my library to a 64 bit signed integer. e.g:

 #ifdef ODBC64
       typedef sint64 SLEN;
 #else
       #define SLEN int
 #endif

When the application passes reference to my library as :

SLEN count;
mylibraryfunction(&count);

the values returned to application looks like these:

sizeof(SLEN) = 8
sizeof(SLEN) in my library = 4
m_AffectedRows BEFORE = 0x3030303030303030
m_AffectedRows AFTER = 0x3030303000000000        0

You can see that the assignment from my lib is copying 4 bytes (value 0). I need to know a way to reset the upper 4 bytes to 0. e.g:

0x0000000000000000

I have tried both static_cast and reinterpret_cast, but none are helpful.

like image 801
Saba Kauser Avatar asked Nov 07 '22 19:11

Saba Kauser


1 Answers

I made a MCVE where I resembled what happens in OPs case.

I even didn't need an extra library for this, just two translation units (resulting in two object files).

First lib.cc:

#include <cstdint>

extern "C" void func(int32_t *pValue);

void func(std::int32_t *pValue)
{
  *pValue = 0;
}

Second prog.cc:

#include <iostream>
#include <iomanip>

// how prog.cc "knows" func():
extern "C" void func(int64_t *pValue);

int main()
{
  int64_t value = 0x0123456789ABCDEFull;
  std::cout << "value before: " << std::hex << value << '\n';
  func(&value);
  std::cout << "value after : " << std::hex << value << '\n';
  return 0;
}

Compiler errors? No. Each translation unit uses prototype of func() conformant.

Linker errors? No. The symbols match, anything else is beyond view of linker.

I must admit I had to use extern "C" to achieve this. Otherwise, at least, the C++ name mangling had prevented the proper linking. (When I became aware of this, I made code in C.)

Output:

value before: 123456789abcdef
value after : 123456700000000

Live Demo on wandbox

This is very dangerous! Any use of any extern symbol should use a 100 % compatible declaration. (And yes, C and C++ provide various ways to shoot into your own foot.)


Imagine what would happen if the lib.cc function func() would write int64_t where the prog.cc would pass a pointer to int32_t: Out of bound access with possible more disastrous consequences.

like image 194
Scheff's Cat Avatar answered Nov 14 '22 22:11

Scheff's Cat