How to convert ascii number to uint64 in C? - c

I'm using Mini Ini to read data from .ini files on an embedded system. It supports reading in long integers or strings. Some of the numbers I have are too large to fit in a long, so I am reading them in as a string. However, I need to then convert them to a uint64_t.
I attempted to convert it to a float using atof and casting that to a uint64_t, which crashed and burned, presumably because casting changes how the program views the bits without changing the bits themselves.
char string_in[100];
//ret = ini_gets(section,key,"default_value",string_in,100,inifile);
//To simplify, use
string_in = "5100200300";
uint64_t value = (uint64_t)atof(string_in);
I would appreciate help on how to convert a string to a uint64.
EDIT: Conclusion
The atoll function converts ascii to long long, which serves the purpose I needed. However, for the sake of completeness, I implemented the function provided in the accepted answer and that provided the exact answer to my question.

You could write your own conversion function:
uint64_t convert(const char *text)
{
uint64_t number=0;
for(; *text; text++)
{
char digit=*text-'0';
number=(number*10)+digit;
}
return number;
}

#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
static_assert(sizeof(uint64_t) == sizeof(long long),
"Your system is mighty weird");
uint64_t u64 = strtoull(string, NULL, 10);

Related

How to print long double number in xinu?

Function sqrtl doesn't work here, also the printf of long double prints f for all given numbers:
#include <conf.h>
#include <kernel.h>
#include <math.h>
#include <float.h>
long double sqrtn;
unsigned long int n;
void xmain() {
unsigned long int n;
printf("Enter unsigned long integer:\n");
scanf("%lu", &n);
sqrtn = sqrtl(long double)n);
printf("\nsqrtn=%Lf\n", sqrtn);
} /* main */
I downloaded the Xinu source code for x86 from https://xinu.cs.purdue.edu/files/Xinu-code-Galileo.tar.gz .
Looking at the implementation for printf (lib/printf.c lib/doprnt.c), as far as I can tell it simply doesn't support length modifiers. That means that, for example, this:
long int n = 42;
printf("%ld\n", n);
wouldn't work. I suggest trying that on your system.
This is not a conforming C implementation (and it's probably not intended to be).
It does appear to support most of the standard conversion specifiers ("%d", "%u", "%x", "%f", etc.).
If you want to print a long double value, I think the best you can do is either convert it to double and use "%f" (which could lose range and/or precision) or write your own code to convert a long double value to a string. (Or run you code on a different system).
Disclaimer: I haven't tried this, I've only examined the source code, and only for the x86 version of the system.
I was worried about long double won't print.
i wrote a small test and found out that my MAC wanted to have %Lf or %Le.
it seems that capital L must be used.

ATmega64a float to IEEE-754 unexpected result

I am trying to convert a float to an IEEE-754 Hex representation. The following code works on my Mac.
#include <stdio.h>
#include <stdlib.h>
union Data {
int i;
float f;
};
int main() {
float var = 502.7;
union Data value;
value.f = var;
printf("%08X\n", value.i);
return 0;
}
This is giving me the expected result of 43FB599A.
When I run this code on an ATmega64a I am getting 0000599A not 04A2599A as originally posted which was a mistake.
The first two bytes are not expected but the final two bytes seem correct?
Any ideas?
As mentioned in the accepted answer the I was assuming that int was 4 bytes. I was writing the code on my mac and sending it to someone that was downloading it to an 8-bit ATmega64a. On the ATmega64a int is 2 bytes, not 4. I changed int to unsigned long which is 4 bytes on the ATmega64a.
In addition, I had to add a length sub-specifier of l to the format given to printf. This is because when given a specifier of x, printf uses a type of unsigned int to interpret the corresponding argument. Adding the length sub-specifier of l tells printf to use the type of unsigned long to interpret the corresponding argument.
Using only the length sub-specifier of l and not changing the variable i to unsigned long was causing printf to grab some extra bytes and output 04A2599A as originally posted. I, of course, needed to change the type of i to unsigned long as well as use the length sub-specifier of l.
http://www.cplusplus.com/reference/cstdio/printf/
This processor is an 8 bit one which mean size of int is most likely 2 byte not 4 as your code assume.
Try to use uint32_t rather then int if you can.

How can I store the bits of a uint64_t inside of a double?

Basically I have a uint64_t whose actual value I do not care about. I need to store it in a double so that I can easily store the bits in an object in R (if you don't know what that is, that's fine, it doesn't matter for the question).
So what I would like is a means of storing the 64 bits of the uint64_t inside of a double and then also convert from the double holding the bits back to the original uint64_t.
I've been banging my head against the wall on this for a quite a bit (is that a pun?) so any and all help is greatly appreciated!!!
As stated in the comments, you can use memcpy to copy the bits from your uint64_t to a double.
This works because the size of a double is the same as the one of an uint64_t (8 bytes).
If you try to display the values, you won't get the same result, though. Indeed a double stores both positive and negative values, with a floating point, whereas an uint64_t is... unsigned and whole.
The binary representation is the same, the interpreted value is different.
in C casting is your friend:
dbl = * (double*)(&ui64);
ui64 = * (uint64_t*)(&dbl);
example:
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
double dbl_1 = 42.42;
uint64_t ui64_1;
double dbl_2;
uint64_t ui64_2 = 0x404535C28F5C28F6;
void main(void)
{
ui64_1 = *(uint64_t*)(&dbl_1);
printf("%" PRIx64 "\n", ui64_1);
dbl_2 = *(double*)(&ui64_2);
printf("%f", dbl_2);
}
Great resource for conversions:
IEEE-754 Floating-Point Conversion
Edit: This is undefined behavior per the C standards and although it may work, it is not best practice.

Assigning Value to unsigned long long in C

While assigning value to a unsigned long long variable in C, value of variable is not getting assigned properly. The code is:
#include <stdio.h>
int main()
{
unsigned long long x;
printf("%d\n\n",sizeof(x));
x=0xAAAAAAAAAAAAAAAAULL;
printf("%u\n\n",x);
printf("%ld\n\n",x);
return 0;
}
Rightmost 32 bits of the variable are being ignored. Can someone please tell me how to do this correctly.
Print unsigned long long with %llu.
Use llu or Lu format specifier for printf if you want to print unsigned long long. The format specifier depends on the compiler.
The assignment occurs correctly. However, the program is not displaying the value correctly.
printf("%Lu\n\n",x);
or
printf("%llu\n\n",x);
or maybe even
printf("%LLu\n\n",x);
depending on the compiler and specific runtime library.
You need to change the printfs to print properly.
#include <stdio.h>
int main()
{
unsigned long long x;
printf("%d\n\n",sizeof(x));
x=0xAAAAAAAAAAAAAAAAULL;
printf("%u\n\n",x); // not work
printf("%llu\n\n",x); // works
printf("%016llx\n\n",x); // bonus check
return 0;
}

C convert hex to decimal format

Compiling on linux using gcc.
I would like to convert this to hex. 10 which would be a.
I have managed to do this will the code below.
unsigned int index = 10;
char index_buff[5] = {0};
sprintf(index_buff, "0x%x", index);
data_t.un32Index = port_buff;
However, the problem is that I need to assign it to a structure
and the element I need to assign to is an unsigned int type.
This works however:
data_t.un32index = 0xa;
However, my sample code doesn't work as it thinks I am trying to convert
from an string to a unsigned int.
I have tried this, but this also failed
data_t.un32index = (unsigned int) *index_buff;
Many thanks for any advice,
Huh? The decimal/hex doesn't matter if you have the value in a variable. Just do
data_t.un32index = index;
Decimal and hex are just notation when printing numbers so humans can read them.
For a C (or C++, or Java, or any of a number of languages where these types are "primitives" with semantics closely matching those of machine registers) integer variable, the value it holds can never be said to "be in hex".
The value is held in binary (in all typical modern electronic computers, which are digital and binary in nature) in the memory or register backing the variable, and you can then generate various string representations, which is when you need to pick a base to use.
I agree with the previous answers, but I thought I'd share code that actually converts a hex string to an unsigned integer just to show how it's done:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *hex_value_string = "deadbeef";
unsigned int out;
sscanf(hex_value_string, "%x", &out);
printf("%o %o\n", out, 0xdeadbeef);
printf("%x %x\n", out, 0xdeadbeef);
return 0;
}
Gives this when executed:
emil#lanfear /home/emil/dev $ ./hex
33653337357 33653337357
deadbeef deadbeef
However, my sample code doesn't work as it thinks I am trying to convert from an string to a unsigned int.
This is because when you write the following:
data_t.un32index = index_buff;
you do have a type mismatch. You are trying to assign a character array index_buff to an unsigned int i.e. data_t.un32index.
You should be able to assign the index as suggested directly to data_t.un32index.

Resources