I am working on a function that can convert long binary number to decimal string. I store those binary numbers in a uint32_t array, little-endian. For example, if an array is like uint32_t a[2]{0,1}
, it represents 4294967296
(2^32)
.
Code:
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
char* to_string(uint32_t* data,int size) {
if (size == 0) {
return new char[2]{ '0','\0' };
}
int decimal_size = 10 * size;
char* decimal_res = new char[decimal_size];
for (int i = 0; i < decimal_size; i++) {
decimal_res[i] = 0;
}
int rank = 0;
uint64_t* data_ptr = new uint64_t[size];
for (int i = 0; i < size; i++) {
data_ptr[i] = data[i];
}
int current_index = size - 1;
while (current_index >= 0) {
char remainder = 0;
if (data_ptr[current_index] < 10) {
remainder = data_ptr[current_index];
current_index--;
}
//div
for (int i = current_index; i >= 0; i--) {
((uint32_t*)&data_ptr[i])[1] = remainder;
uint64_t num = data_ptr[i];
//printf("num:%ld\n", num);
data_ptr[i] = num / 10;
remainder = num - data_ptr[i] * 10;
}
if (rank < decimal_size) {
decimal_res[rank] = remainder;
}
else {
abort();
}
rank++;
}
delete[] data_ptr;
while (!decimal_res[rank - 1] && rank > 0) {
rank--;
}
if (rank == 0) {
return new char[2]{ '0','\0' };
delete[] decimal_res;
}
char* real_res = new char[rank + 1];
real_res[rank] = '\0';
for (int i = 0; i < rank; i++) {
real_res[i] = decimal_res[rank - i - 1] + '0';
}
delete[] decimal_res;
return real_res;
}
int main(){
int size=0;
scanf("%d", &size);
uint32_t* raw_data_ptr = new uint32_t[size];
for(int i=0;i<size;i++){
scanf("%ud,",&raw_data_ptr[i]);
}
char * res = to_string(raw_data_ptr,size);
printf("%s",res);
delete[] res;
return 0;
}
Basically, in each loop, I divide this large binary number by 10 and get the remainder. This is working perfectly without -O2 optimization. If I input 2 0 1
, it outputs 4294967296
. But with -O2 optimization, it outputs 0
.
But if I insert a printf
instruction inside the inner loop, with -O2 optimization, it works well. So I looked into the assembly code the compiler generated, it seems that the remove some code I wrote.
Besides, if I replace ((uint32_t*)&data_ptr[i])[1] = remainder;
with ((uint32_t*)data_ptr)[2 * i + 1] = remainder;
, it also works well.
So is it a bug of compiler? Or my code has some undefined behaviours?
compiler version:
g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
system: Ubuntu 20.04