Unexpected result of size_t modulo long unsigned int - c

In the following code, BITS_IN_INT is an long unsigned int with value 32. Why does the modulo operation return the value 0 instead of the expected 20?
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define BITS_IN_INT sizeof(int) * CHAR_BIT
int main()
{
size_t i = 20;
printf("%zu\n", i);
printf("%lu\n", BITS_IN_INT);
printf("%lu\n", i % BITS_IN_INT);
return 0;
}

After macro expansion, the last printf looks like:
printf("%lu\n", i % sizeof(int) * 8);
So, the expression (in printf) is evaluated as if:
(i % sizeof(int)) * 8
If sizeof(int) is 4 (which seems to the case on your platform) then i % sizeof(int) yields 0; 0 * 8 is 0.
Avoid macros if you can. If not, always use parentheses around your macros:
#define BITS_IN_INT (sizeof(int) * CHAR_BIT)
NB: %zu is the correct format specifier for printing size_t values.

Related

How to allocate enough memory to convert an unsigned long long int into string

With a code where I have a struct:
struct fibo_entry { /* Definition of each table entry */
int n;
unsigned long long int lli; /* 64-bit integer */
char *str;
};
I have to solve a Fibonacci sequence where I have the following:
fibo_table = (struct fibo_entry *)malloc(sizeof(struct fibo_entry));
//fibo_table->str = (char *)malloc(1 + 8 * sizeof(char)); // !!??
for (i = 0; i <= n; i++) {
fibo_table[i].n = i;
if (i == 0) {
fibo_table[i].lli = 0;
//sprintf(fibo_table[i].str, "%llu", fibo_table[i].lli);
//fibo_table[i].str = atoi(fibo_table[i].lli);
} else if (i == 1) {
fibo_table[i].lli = 1;
} else {
fibo_table[i].lli = fibo_table[i-1].lli + fibo_table[i-2].lli;
//log10(fibo_table[i].lli);
}
}
The process to calculate Fibonacci is done, the problem that I have comes when I have to calculate the memory that I need to allocate a long long int in the string.
I know that the numbers use 64 bits each and I tried with malloc and the concept that sprintf should work to convert one in another, but I can't find a solution. Every time that I try to run the program, just fail.
If you are writing a (positive) number, n, in decimal notation (as the %llu format specifier will), then the number of digits will be (the integral part of) log10(n) + 1.
So, in order to (pre-)determine the maximum buffer size required, you can use the log10 function on the compiler-defined constant, ULLONG_MAX (this is the maximum value that an unsigned long long int can have). Note that, when allocating the character buffer, you should add 1 to the number of digits, to allow for the nul-terminator in your string.
The following short program may be helpful:
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <limits.h>
int main()
{
size_t maxdigits = (size_t)(log10((double)(ULLONG_MAX)) + 1);
printf("Max. digits in unsigned long long = %zu!\n", maxdigits);
printf("Max. value for the type is: %llu\n", ULLONG_MAX);
return 0;
}
On most modern systems, unsigned long long int will be 64 bits, with a maximum value of 18446744073709551615 (20 digits); however, it is better to use the platform/compiler-specific ULLONG_MAX, rather than relying on any particular value being correct.
Further, rather than calculating this maxdigits value multiple times, you need only calculate a 'global' constant once, then re-use that as and when required.
size_t CountDigit(long long int num)
{
size_t count = 0;
if(num < 0)
{
count++;
}
while (num)
{
count++;
num \=10;
}
count++;\\thats for the '\0'
return (count);
}
then you can use count for malloc and after that you can use sprintf or do it yourself, to insert the right chars in it.
How to allocate enough memory to convert an unsigned long long int into string
With an n-bit unsigned integer, a buffer of log10(2^n - 1) + 1 + 1 is needed. +1 for "ceiling" and +1 for the null character.
To find this value at compiler time, could use:
#define LOG10_2_N 302
#define LOG10_2_D 1000
#define ULL_STR_SIZE1 (sizeof (unsigned long long)*CHAR_BIT * LOG10_2_N / LOG10_2_D + 2)
To find this at pre-processor time is a little trickier as we need to find the bit width via macros. This approach also takes space advantage if rare padding bits are used.
// Numbers of bits in a Mersenne Number
// https://mathworld.wolfram.com/MersenneNumber.html
// https://stackoverflow.com/a/4589384/2410359
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define ULLONG_BIT_WIDTH IMAX_BITS(ULLONG_MAX)
// 28/93 is a tight fraction for log10(2)
#define LOG10_2_N 28
#define LOG10_2_D 93
#define ULL_STR_SIZE2 (ULLONG_BIT_WIDTH * LOG10_2_N / LOG10_2_D + 1 + 1)
ULL_STR_SIZE2 is suitable for #if ULL_STR_SIZE2 ... processing.
fibo_table[i].str = malloc(ULL_STR_SIZE2);
if (fibo_table[i].str) {
sprintf(fibo_table[i].str, "%llu", fibo_table[i].lli);
Or at run-time, to "right size", call snprintf() first and find the size needed for per each integer via the return value of *printf().
int n = snprintf(NULL, 0, "%llu", fibo_table[i].lli);
fibo_table[i].str = malloc(n + 1);
if (fibo_table[i].str) {
sprintf(fibo_table[i].str, "%llu", fibo_table[i].lli);
Or slightly more efficient, form a worst case size temporary buffer, write to it and then duplicate the string.
char tmp[ULL_STR_SIZE2];
snprintf(tmp, sizeof tmp, "%llu", fibo_table[i].lli);
fibo_table[i].str = strdup(tmp);
Alternative: change pointer char *str to an array.
struct fibo_entry {
int n;
unsigned long long int lli;
//char *str;
char *str[ULL_STR_SIZE2];
};
and use
snprintf(fibo_table[i].str, sizeof fibo_table[i].str, "%llu", fibo_table[i].lli);
Best to not assume long long is 64-bit. It is at least 64-bit.
You can calculate how many digits you need to use doing something like number_digits = (int)log10((double)num) + 1; and then reserve enough space with fibo_table[i].str = malloc(number_digits * sizeof(char)); remember you need to do this every for iteration, after those two steps you can now use the sprintf as you were sprintf(fibo_table[i].str, "%llu", fibo_table[i].lli);, code would look something like this:
int number_digits;
for (i = 0; i <= n; i++) {
if (i == 0) {
....
} else if (i == 1) {
....
} else {
....
}
number_digits = (int)log10((double)i) + 1;
fibo_table[i].str = malloc(number_digits*sizeof(char));
sprintf(fibo_table[i].str, "%llu", fibo_table[i].lli);
}

Why does the below code yield O/P as 3 instead of 5?

In the below code length of string s in 3 and length of t is 5. So, 3-5 = -2 which is smaller than 0. Then, why does the below code print 3?
#include <stdio.h>
#include <string.h>
void printlength(char *s, char *t){
unsigned int i=0;
int len = ((strlen(s) - strlen(t))> i ? strlen(s):strlen(t));
printf("%d",len);
}
int main()
{
char *x ="abc";
char *y ="defgh";
printlength(x,y);
return 0;
}
when -2 is converted to an unsigned int the result is the unsigned int value (UINT_MAX + 1- 2 or UINT_MAX - 1) , which is greater than i. strlen returns size_t which is an unsigned data type.
Also size_t is the correct type for len which we would print with printf("%zu",len).
Suprisingly when you compared the result of subtraction with i and the value of i is 0. You can do this
size_t slen = strlen(s);
size_t tlen = strlen(t);
printf("%zu\n", (slen > tlen)? slen : tlen);
Your problem is with subtracting greater unsigned value from the smaller one.
`(unsigned) 3 - (unsigned) 5` = (unsigned) 4294967294 which is > 0.
Use proper types for your calculations and proper logic. Remember that strlen returns value of type size_t.
No need to repeat strlen operation for the same string.
The improved version of your program could look like this:
#include <stdio.h>
#include <string.h>
void printlength(char *s, char *t){
size_t len;
size_t sLen = strlen(s);
size_t tLen = strlen(t);
if(sLen > tLen)
len = sLen - tLen;
else
len = tLen - sLen;
printf("len = %u\n\n",len);
printf("NOTE: (unsigned) 3 - (unsigned) 5 = %u", -2);
}
int main()
{
char *x ="abc";
char *y ="defgh";
printlength(x,y);
return 0;
}
OUTPUT:
len = 2
NOTE: (unsigned) 3 - (unsigned) 5 = 4294967294
So, 3-5 = -2
Thats for signed ints, for size_t which strlen() returns and is unsigned, that's a pretty big number.
The prototype of strlen() is:
size_t strlen ( const char * );
It's return value type is size_t, which in most cases, is an unsigned integer type (usually unsigned int or unsigned long.
When you do subtraction between two unsigned integers, it will underflow and wrap around if the result is lower than 0, the smallest unsigned integer. Therefore on a typical 32-bit system, 3U - 5U == 4294967294U and on a typical 64-bit system, 3UL - 5UL == 18446744073709551614UL. Your test of (strlen(s) - strlen(t)) > i has exactly the same behavior of strlen(s) == strlen(t) when i == 0, as their length being identical is the only case that could render the test being false.
It's advised to avoid using subtraction when comparing intergers. If you really want to to that, addition is better:
strlen(s) > strlen(t) + i
This way it's less likely to have unsigned integer overflow.
By the way, if you save the length of the strings in variables, you can reduce an extra call to strlen(). And since you do not modify the strings in your function, it is better to declare the function parameters as const char*. It's also recommended that you do
const char *x ="abc";
const char *y ="defgh";
since string literals cannot be modified. Any attempt to modify a string literal invokes undefined behavior.

unsigned integer getting overflowed in c [duplicate]

This question already has answers here:
Unsigned int in C behaves negative
(8 answers)
Closed 8 years ago.
I wrote simple C program to find the maximum positive number I can reach using unsigned integer as given below. Size of integer on my machine is 4 bytes.
#include <stdio.h>
#include <math.h>
main()
{
unsigned int x = 1;
int i = 1;
for(; i <= 31; i++)
{
x = x * 2;
}
unsigned int y = pow(2, 31);
printf("%d\n", x);
printf("%d\n", y);
}
both x, y are getting overflowed and value as -2147483648. I thought it should not overflow because on the machines where sizeof(int) = 4 bytes, unsigned int range should be pow(2, 32) - 1. Can any one please let me know why this is getting overflowed?
You want to use %u for unsigned int:
printf("%u\n", x);
printf("%u\n", y);

Discrepancy in size of long int

I'm getting a size discepancy while using long int in C. The following code:
#include <stdio.h>
void main()
{
printf("%d\n", sizeof(long int));
}
gives 8 as output, so 64 bits are used to represent long int, right? But:
#include <stdio.h>
void main()
{
long int a;
a = 1;
a = a << 32;
printf("%d\n", a);
}
gives 0 (shifting by 31 gives -2147483648, which is -2**31). So, it seems that only 4 bytes are being used. What does this mean? I'm using gcc 4.4.5 with no flags
You're printing it as a normal integer: printf("%d"). Try printing it as a long integer: printf("%ld ...").

weird output without typecasting

I was trying to execute this code through gcc compiler:
#include <stdio.h>
int main()
{
unsigned long long int x;
x = 75000 * 75000;
printf ("%llu\n", x);
return 0;
}
But it gave wrong output.
I then tried this:
#include <stdio.h>
int main()
{
unsigned long long int x;
x = (unsigned long long)75000 * (unsigned long long)75000;
printf ("%llu\n", x);
return 0;
}
And it gave correct output !
Why is this so?
The expression 75000 * 75000 is the multiplication of two integer constants. The result of this expression is also an integer and can overflow. The result is then assigned to an unsigned long long, but it has already overflowed so the result is wrong.
To write unsigned long long constants use the ULL suffix.
x = 75000ULL * 75000ULL;
Now the multiplication will not overflow.

Resources