iammilind
iammilind

Reputation: 70000

Why does storing an 32-bit unsigned int value of -1 in SQLite DB and reading it back result in the value getting changed to half?

In its simplest form, below is a pseudo code of the problem:

enum E { VALUE = -1; }
uint32_t value = VALUE;  // signed to unsigned conversion without typecasting
SQLiteDB.INSERT(<table containing `value`>);
SQLiteDB.SELECT(<same table as above>);

In the DB, I see that the value is stored as 4294967295 (i.e. 0xFFFFFFFF) which is correct. But when the value is read from the DB, it is truncated as 2147483647 (0x7FFFFFFF) which is appx half of the original value.

Why is that? How to solve this problem?

Update: As informed above, the value 0xFFFFFFFF is visible in SQLite properly, but when read in the uint32_t back, it's truncated. Possibly is it a data loss?
Below is an image seen with SQLiteBrowser on the actual data.

enter image description here


Related but not duplicate:

Upvotes: 1

Views: 677

Answers (1)

iammilind
iammilind

Reputation: 70000

Found the issue. I am using a library code to read the DB tables. Which gets the values in form of string properly. Further std::stoi() is used for converting to the desired uint32_t.

Now 4294967295 is too big of an integer for an std::stoi(). In fact in Ubuntu 64-bit machine, it throws an exception. However in Windows, somehow it truncates by resetting the sign bit to 0 and hence it becomes 2147483647. May be this is a consistent undefined behaviour. :-)

Instead of std::stoi(), if we use std::stol() or ::strtoul(), then that resolves the problem and the value is read correctly as 4294967295 to a uint32_t variable.

Upvotes: 2

Related Questions