Why does printf convert large numbers? - c

Why doesn't this work?
printf("%d \n\n\n\n", atoi("11110010100"));
it outputs -1774891788... I just want it outputted as it is. It seems to work just fine if the number is a bit smaller.

atoi returns an int. You pass a string which contains a number bigger than what int(in your implementation) can hold. So, you have an integer overflow.
To print the maximum value an int can hold, include limits.h and print INT_MAX.

int atoi (const char * str) convert string to integer,and the basic signed integer type capable of containing at least the [−32767,+32767] range,
the 11110010100 is bigger than integer storage capability, so you have an overflow.
you can try this method to parse a String to a Double: atof
http://www.lemoda.net/c/string-to-double/

Related

Difference in the values of atoi

I have the following code:
char* input = (char*)malloc(sizeof(char) * BUFFER) // buffer is defined to 100
int digit = atoi(input); // convert char into a digit
int digit_check = 0;
digit_check += digit % 10; // get last value of digit
When I run the input 1234567896 and similarly digit = 1234567896 and digit_check = 6.
However when I run the input 9999999998, digit = 1410065406 and therefore digit_check = 6 when it should be 8.
For the second example, why is there a difference between input and digit when it should be the same value?
Probably because 9999999998 is bigger then the maximum (signed) integer representation, so you get an overflow.
In fact this is the binary representation of 9999999998 and 1410065406:
10 01010100 00001011 11100011 11111110
01010100 00001011 11100011 11111110
As you can see if you see 1410065406 is the 32ed bit value of 9999999998
atoi is limited to an int size (32 bits on most recent plateform).
If you want to handle large numbers, you can use atol or scanf("%ld").
Don't forget to type your variable to long int (or long).
You could also just getting the very last character of your input (gathered as a string rather than as an int) and use atoi on it, so it would never overflow.
On many platforms size of int is limited by 4 bytes, that limits digit in [-2 ** 31, 2**31 - 1].
Use long (or long long) with strtol (or strtoll) depending on platform you build for. For example, GCC on x86 will have 64-bit long long, and for amd64 it will have 64-bit long and long long types.
So:
long long digit = strtoll(input, NULL, 10);
NOTE: strtoll() is popular in Unix-like systems and became standard in C++11, but not all VC++ implementations have it. Use _strtoi64() instead:
__int64 digit = _strtoi64(input, NULL, 10);
You probably want to use the atoll function, which returns a long long int, that is twice as big as int (most likely 64 bits in your case).
It is declared in stdlib.h
http://linux.die.net/man/3/atoll
You should avoid to call atoi on uninitialized string, if there is no \0 on the string, you will invalid read and have a segmentation fault.
You should use strtoimax instead, it's more safe.
9999999998 is bigger then the maximum value that an integer can represent. Either use atol() OR atoll()
You should stop using atoi function or any other functions from ato... group. These functions are not officially deprecated, but they are effectively abandoned since 1995 and exist only for legacy code compatibility purposes. Forget about these functions as if they do not exist. These function provide no usable feedback in case of error or overflow. And overflow is what apparently happens in your example.
In order to convert strings to numbers, C standard library provides strtol function and other functions from strto... group. These are the functions you should use to perform the conversion. And don't forget to check the result for overflow: strto... functions provide this feedback through the return value and errno variable.

Converting from long to hex in C?

I have this code
char binary[] = "0001001010000011";
long number = strtol(binary, NULL, 16);
printf("%x", number);
I want to convert the string into a hex number. the answer is 1283, but i am getting DF023BCF what am i doing wrong?
The base you specify to strtol is the base to use to parse the input, not the output (which instead is specified by the %x). IOW, that code says to strtol to parse 0001001010000011 as if it were a hexadecimal number (and, by the way, it results in overflow).
The last parameter to strtol is the base that you want to convert from. Since you are providing a binary encoded string you should specify a base 2 conversion.
Here is the correct code:
char binary[] = "0001001010000011";
long number = strtol(binary, NULL, 2);
printf("%x", number);
I would also suggest that binary numbers are not normally signed (especially when 17 digits long), therefore, it seems likely that you may want to use the unsigned version of the function, strtoul() as shown below. Finally, when printf'ing a number into hex format it might be a good idea to indicate hexadecimal with a leading 0x marker. In your case, the answer is 0x1283 but displaying this number as 1283 allows it to be easily confused as a decimal number. Both suggestions are shown below.
const char binary[] = "0001001010000011";
unsigned long number = strtoul(binary, NULL, 2);
printf("0x%x", number);

Printing hex integer by casting to char* and using "%s" in sprintf

I'm reading in two 32 bit registers and trying to put it inside a string buffer using the following:
sprintf (buffer, "%s-%s", ((char*)(in32(REGISTER1))) , (char*)(in32(REGISTER2)));
Can the hex value read in from the registers not be typecast as a pointer to a char and be printed into the buffer as above?
As craig65535 implies in a comment above, the problem is most likely with this phrase:
the hex value read in from the registers
I doubt that you're reading in a hex value; rather, you're reading in an integer. If you want to store a hex representation of that integer in a string, you'd use the %X format specifier:
sprintf (buffer, "%08X-%08X", in32(REGISTER1), in32(REGISTER2));
(The 8 means "use a width of eight characters"; the 0 means "left-pad with zeroes if the value is such that the width is less than eight".)
The only way you could validly cast to char * is if the integer value in the register is actually a pointer to some memory location where you've stored a string; but that is clearly not the case here.
sprintf(buffer, "%08x-%08x", REGISTER1, REGISTER2);
-- that's assuming you want the register addresses in your buffer. If your intention is to read the contents of the registers, adjust accordingly. The point though is you cannot simply call a number a char* and get the number out of it, but sprintf() (and all printf-like functions) can convert value bases for you.
As the others answers suggest, you can convert your integer to a string hex representation with sprintf using %X.
But as you didn't said what compiler you use or what the length of integer or long is, you could get unexpected results.
On a 16bit controller sprintf (buffer, "%08X-%08X", in32(REGISTER1),in32(REGISTER2)); would fail.
This should work on the most plattforms, as sprintf assume long values as arguments, and the arguments are always casted to longs.
sprintf (buffer, "%08lX-%08lX", (long)in32(REGISTER1), (long)in32(REGISTER2));

Printing a very large whole number in C

I've stored a very large number in a float variable, but when I print it I want to only display the whole number part and nothing after the decimal point.
For numbers in the int or long range, I would do a casting but this hasn't helped me because the number I want to print is too long for int or long.
I've looked at this explanation: http://www.cprogramming.com/tutorial/printf-format-strings.html but I haven't succeeded in solving this.
this is my code and my attempt to do the casting:
double sum=552074001368;
long long_sum;
long_sum = (long)(sum); //int casting for double "add"
if(sum>=0) printf("=\n%ld\n",long_sum);
else printf("=\n%ld\n",-long_sum);
I don't want to use a specific precision like printf("%15f") because this variable fluctuates and is sometimes very short like 4 digits.
Use the precision modifier .0 and print the floor of the number:
printf("%.0f\n", floor(sum));
(Or the floor of the abs, if you want only the magnitude, as in your example code.)
I think what you're after is %.0f. For example:
#include <stdio.h>
int main(){
double x = 1234.567;
printf("%.0f", x);
return 0;
}
...prints:
1235
Why are you casting to long at all? Use the printf format specifiers to control what and how many characters are printed.
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
Remember that both the width and the precision can be specified by a variable and doesn't have to be known at compile time:
printf("=\n%.*lf\n", 4, sum); // print 4 places behind the decimal point
int i;
i = 5;
// print only the whole number part of sum and output at least i characters,
// pad with leading spaces if number requires fewer than i characters
printf("=\n%*.*lf\n", i, 0, sum);
This line is problematic:
double sum=552074001368;
Since that is an integer literal, the compiler will first check if the number will fit in an int, then long, then long long. If it won't fit in long long I suspect you'll get either a compiler error or undefined behavior wrap-around, I'm not sure of which.
If your compiler supports long long, then the code will work and the number will be stored in a temporary long long (which will be optimized away). This long long is then stored inside a double.
Instead, write like this:
double sum=552074001368.0;
The .0 syntax gives you a double floating point literal without involving integer types at all.
double sum=552074001368LL;
long long long_sum;
long_sum = (long long)(sum);
if(sum>=0) printf("=\n%lld\n",long_sum);
else printf("=\n%lld\n",-long_sum);

C - Convert long int to signed hex string

MASSIVE EDIT:
I have a long int variable that I need to convert to a signed 24bit hexadecimal string without the "0x" at the start. The string must be 6 characters followed by a string terminator '\0', so leading zeros need to be added.
Examples:
[-1 -> FFFFFF] ---
[1 -> 000001] ---
[71 -> 000047]
Answer
This seems to do the trick:
long int number = 37;
char string[7];
snprintf (string, 7, "%lX", number);
Because you only want six digits, you are probably going to have to do some masking to make sure that the number is as you require. Something like this:
sprintf(buffer, "%06lx", (unsigned long)val & 0xFFFFFFUL);
Be aware that you are mapping all long integers into a small range of representations. You may want to check the number is in a specific range before printing it (E.g. -2^23 < x < 2^23 - 1)
Look at sprintf. The %lx specifier does what you want.
Use itoa. It takes the desired base as an argument.
Or on second thought, no. Use sprintf, which is standard-compliant.
In the title you say you want a signed hex string, but all your examples are unsigned hex strings. Assuming the examples are what you want, the easiest way is
sprintf(buffer, "%06X", (int)value & 0xffffff);

Resources