strtoull "seems" to return a wrong value - c

Basically I am trying to convert hex strings into unsigned long long values using strtoull. Here's the simple code
#include <stdio.h>
#include <string.h>
int main ()
{
unsigned long long val =0;
//printf("sizeof(unsigned long long)=%d\n", sizeof(unsigned long long));
val = strtoull("0x8004298c42ULL",NULL,16);
printf("%llx\n", val);
if ( val == 0x8004298c42ULL)
{
printf("Success\n");
}
return 0;
}
I expect val to print 8004298c42 but it prints 4298c42. The 8 is being chopped off. I tried without the 0x and without the ULL too. But still the same result. Just to make sure that I am not missing out on some trivial printf format specifier thing, I even checked the contents of val. Still no use( ie Success was not printed )
I think I am missing out something trivial but don't know what!

The function strtoull() is declared in <stdlib.h>, not <string.h>, so the compiler thinks it returns an int, not an unsigned long long.
Cure: make sure that all functions are declared before they are used. If you use gcc, then you should consider some combination of -Wall, -Wextra, -Wstrict-prototypes, -Wmissing-prototypes, -Wold-style-declaration, -Wold-style-definition and -Werror.

Related

C printf of an integer with %lu produces large number

I know that is bad practice to print an integer with %lu which is a unsigned long. In a project i was working on i got a large number when trying to print 11 with %lu in the snprint format.(old code) I am using gcc 4.9.3.
This code below i thought would produce the wrong number since snprintf is told to read more than the 4 bytes occupied. Its doesnt though. Works perfectly. It reads everything correctly. Either it does not go past the 4 bytes in to the unknown or the extra 4 bytes in the long are fully of zeros when it gets promoted to long from int.
I am wondering out of curiosity is when does printf print the wrong number? What conditions does it need produce a wrong big number? There has to be garbage in the upper 4 bytes but it seems like it does not set that garbage for me.
I read the answers here but the code worked for me. I know its a different compiler.
Printing int type with %lu - C+XINU
#include<inttypes.h>
#include<stdio.h>
int main(void){
uint32_t number1 = 11;
char sentence[40];
snprintf(sentence,40,"Small number :%lu , Big number:%lu \n",number1,285212672);
printf(sentence);
}
On OP's machine, uint32_t, unsigned long and int appear to be the same size #R Sahu. OP's code is not portable and may produce incorrect output on another machine.
when does printf print the wrong number?
Use the matching printf() specifier for truly portable code. Using mis-matched specifiers may print the wrong number.
The output string may be well over 40 characters. Better to use a generous or right-sized buffer.
#include <inttypes.h>
#include <stdio.h>
int main(void){
uint32_t number1 = 11;
// char sentence[40];
char sentence[80];
snprintf(sentence, sizeof sentence,
"Small number :%" PRIu32 " , Big number:%d \n",
number1, 285212672);
// printf(sentence); // Best not to print a string using the printf() format parameter
fputs(sentence, stdout);
}

C program Printf function showing unusual behavior for unsigned long long type?

Please consider the below program and observe the output.
#include <stdio.h>
int main()
{
unsigned long long val ;
val =144111444250;
printf ("%llu\n", val);
printf ("%u %llu\n",val, val);
return 0;
}
output:
144111444250
33 10211385600662044705
Using %llu in first printf gives correct result but using %llu in second printf is giving wrong result.
This is undefined behaviour: printf expects an unsigned int for %u but you provide an unsigned long long int, whatever happens after that is up to the whimsy of the compiler.
The format specifiers for printf and scanf not only indicate how something should be printed/scanned, but also what kind of arguments to expect. If you lie you can't expect the results to be reasonable.

How to convert ascii number to uint64 in 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);

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;
}

Printing int type with %lu - C+XINU

I have a given code, in my opinion there is something wrong with that code:
I compile under XINU.
The next variables are relevant :
unsigned long ularray[];
int num;
char str[100];
There is a function returns int:
int func(int i)
{
return ularray[i];
}
now the code is like this:
num = func(i);
sprintf(str, "number = %lu\n", num);
printf(str);
The problem is I get big numbers while printing with %lu, which is not correct.
If i change the %lu to %d, i get the correct number.
For example: with %lu i get 27654342, while with %d i get 26, the latter is correct;
The variables are given, the declaration of the function is given, i write the body but it must return int;
My questions are:
I'm not familiar with 'sprintf' maybe the problem is there?
I assigned unsigned long to int and then print the int with %lu, is That correct?
How can i fix the problem?
Thanks in advance.
Thanks everyone for answering.
I just want to mention I'm working under XINU, well i changed the order of the compilation of the files and what you know... its working and showing same numbers on %lu and %d.
I'm well aware that assigning 'unsigned long' to int and then printing with %lu is incorrect coding and may result loss of data.
But as i said, the code is given, i couldn't change the variables and the printing command.
I had no errors or warnings btw.
I have no idea why changing the compilation order fixed the problem, if someone have an idea you are more then welcome to share.
I want to thank all of you who tried to help me.
I assigned unsigned long to int and then print the int with %lu, is That correct?
No, it isn't correct at all. Think about it a bit! Printf tries to access the memory represented by the variables you pass in and in your case, unsigned long is represented on more bits than int, hence when printf is told to print an unsigned int, it'll read past your actual int and read some other memory which is probably garbage, hence the random numbers. If printf had a prototype mentioning an unsigned long exactly, the compiler could perform an implicit cast and fill the rest of the unwanted memory with zeroes, but since it's not the case, you have to do either one of these solutions:
One, explicit cast your variable:
printf("%lu", (unsigned long)i);
Two, use the correct format specifier:
printf("%d", i);
Also, there are problems with assigning an unsigned long to an int - if the long contains a too big number, then it won't fit into the int and get truncated.
1) the misunderstanding is format specifiers in general
2) num is an int -- therefore, %d is correct when an int is what you want to print.
3) ideally
int func(int i) would be unsigned long func(size_t i)
and int num would be unsigned long num
and sprintf(str, "number = %d\n", num); would be sprintf(str, "number = %lu\n", num);
that way, there would be no narrowing and no conversions -- the type/values would be correctly preserved throughout execution.
and to be pedantic, printf should be printf("%s", str);
if you turn your warning levels way up, your compiler will warn you of some of these things. i have been programming for a long time, and i still leave the warning level obnoxiously high (by some people's standards).
If you have an int, use %d (or %u for unsigned int). If you have a long, use %ld (or %lu for unsigned long).
If you tell printf that you're giving it a long but only pass an int, you'll print random garbage. (Technically that would be undefined behavior.)
It doesn't matter if that int somehow "came from" a long. Once you've assigned it to something shorter, the extra bytes are lost. You only have a int left.
I assigned unsigned long to int and then print the int with %lu, is That correct?
No, and I suggest not casting to int first or else simply using int as the array type. It seems senseless to store a much larger representation and only use a smaller one. Either way, the sprint results will always be off until you properly pair the type (technically the encoding) of the variable with the format's conversion specifier. This means that if you pass an unsigned long, use %ul, if it's an int, use either %i or %d (the difference is that %d is always base-10, %i can take additional specifiers to print in other bases.
How can I fix the problem?
Change the return of your func and the encoding of num to unsigned long
unsigned long ularray[];
unsigned long num;
char str[100];
unsigned long func(int i)
{
return ularray[i];
}

Resources