Can you explain the output of the following structure code? - c

I have searched many articles on google for following question but still not find any good answer.
From my first look ,I able to get that int x:3 here 3 is width if we assign x value greater than 3 some negative value get printed and if we assign value less than 3 ,the assigned value to x get printed correctly.
Can anyone explain how the output is coming of this code.
#include<stdio.h>
1 struct Point
2 {
3 int x:3, y:4;
4 };
5
6 int main()
7 {
8 struct Point p1 = {6,3};
9
10 printf ("x = %d, y = %d", p1.x, p1.y);
11
12 return 0;
13 }
The output comes as:
x = -2, y = 3
when i included stdio.h header file warning vanished but the output of x get chnaged first without header file the value of x is coming -4 now with stdio.h header file the value of x becomes -2.Why this is happening??
Thanks in advance!!

You are trying to store the value 6 into a signed integer of 3 bits, where there are 2 value bits and 1 bit reserved for the sign. Therefore the value 6, which cannot fit in the 2 value bits, is converted to a signed value in an implementation-defined manner. Apparently by using Two's complement.
"warning: overflow in implicit constant conversion" tells you just that. The compiler tries show constant 6 into the signed type bit field. I cannot fit - you get an overflow, and then there's an implicit type conversion to signed type.

Related

Error obtaining logarithms of base 2 in c

I want to obtain the binary logarithms of the numbers 1 to 2048, but I don´t know why it doesn´t work, it doesn´t obtain the right numbers.
If I use floats, it works, but it used to work with integers, i have already done a program with this method and now it doesn´t work because of that. Changing the unsigned int to int doesn´t work. Someone knows why?
for(unsigned int numero=1;numero<=2048;numero*=2)
{
int x=log10(numero)/log10(2);
printf("%d\n",x);
}
return 0;
It prints:
0 1 2 2 4 5 5 6 8 9 10 11
It should be:
0 1 2 3 4 5 6 7 8 9 10 11
Looks like it works for some numbers, but i don´t understand why it doesn´t work for all numbers.
log10 returns a floating point number (double). The value of log10 is not exactly representible in floating point for most numbers you pass, therefore you might get something like log10(8)/log10(2) == 2.9999999 instead of an exact 3. The conversion to int truncates it down to 2. To fix that you should round properly:
int x = lrint(log10(numero)/log10(2));
Or in case your compiler doesn't have the lrint function you can use:
int x = log10(numero)/log10(2) + 0.5;
which would work for this case.
Notice that there are alternative ways to calculate the desired result. Since floating-point numbers already store the exponent in base 2, you can retrieve it with a call to frexp:
int x;
frexp(numero, &x);
Another way would be to avoid floating point math altogether and use an intrinsic to get the index of the last bit set in numero. Unfortunately there's no cross-platform way to do that.

Why does multiplying uint8_t with an integer result in a 0?

I tried to code a program, but i'm having problems with 1 small segment.
for(uint8_t i = 1; i < MAX_BIT_VALUE; i*=2){
printf("Current value of i: %u\n", i);
}
When I run this segment, I get this output:
Current value of i: 0
Current value of i: 0
Current value of i: 0
Current value of i: 0
in an infinite loop. I don't understand why. uint8_t is an unsigned integer of 8-bits. I merely multiplied i which has value 1 by 2. How could it possibly become 0?
If i changed the data type of i to int however, it works just fine:
Current value of i: 1
Current value of i: 2
Current value of i: 4
Current value of i: 8
Current value of i: 16
...
I tried to find a possible answer online, but I don't know how to phrase the problem to get an answer. Could you guys help me please?
Apart from what the other answer recommend on the printing, you have the following problem:
multipy i==128 by 2
result 256
storing it 256 (0x100) in an unsigned 8bit results in 0,
because 8 bit are to narrow
multiply 0 by 2
result 0
0 < 255 -> endless loop
Your code causes undefined behavior.
The flag value # is not supposed to be used with u conversion specifier.
Quoting C11,chapter §7.21.6.1
# The result is converted to an ‘‘alternative form’’. For o conversion, it increases
the precision, if and only if necessary, to force the first digit of the result to be a
zero (if the value and precision are both 0, a single 0 is printed). For x (or X)
conversion, a nonzero result has 0x (or 0X) prefixed to it. For a, A, e, E, f, F, g,
and G conversions, the result of converting a floating-point number always
contains a decimal-point character, even if no digits follow it. (Normally, a
decimal-point character appears in the result of these conversions only if a digit
follows it.) For g and G conversions, trailing zeros are not removed from the
result. For other conversions, the behavior is undefined.
For fixed width integers use the format specifier MACROS as defined in inttypes.h, like PRIu8 for a 8-bit unsigned integer type.
After you fix this the next problem is, overflow of the 8-bit variable. As described in the other answer by Yunnosch Once i becomes 128, you multiple it by 2, and store the result back in the 8-bit variable, the result is 0. Then,
0 multiplied by anything remains 0
which constitutes a forever TRUE condition in the for loop, i < MAX_BIT_VALUE part.
and you get the infinite loop.
Change the printf format string from:
printf("Current value of i: %#u\n", i);
to
printf("Current value of i: %"PRIu8"\n", i);
and it should be fine. The PRIu8 macro is defined in inttypes.h

How this C struct outputs the value?

I am beginner in C and can't understood how this piece of code is working:
struct marks{
int p:3;
int c:3;
int m:2;
};
void main(){
struct marks s={2,-6,5};
printf("%d %d %d", s.p, s.c, s.m);
}
I found that the output is: 2 2 1
But after a lot of try I was unable to figure out how the output is like that. I have less knowledge about the struct. That's why may be I am feeling some problem here.
Well, inside the struct you defined- p:3, c:2, m:2 are actually denoting the bit fields. To know more about bit fields in C go through this link in SO or this link in Wikipedia.
For simplicity, know that the 3 or 2 after the colon(:) sign is representing bit-fields of width 3 or 2. That means 3 or 2 adjacent computer memory locations which have been allocated to hold a sequence of bits.
Now, inside the main() function of your code:
struct marks s={2,-6,5};
Here,
Binary value of 2: 00000010
Binary value of -6: 11111010
Binary value of 5: 00000101
Now according to bit-fields, from binary value of 2, we will take last 3 digits which is 010 (in decimal it is 2) and from binary value of -6, we will take last 2 digits which is 10 (in decimal it is 2) and from binary value of 5, we will take last 3 digits which is 01 (in decimal it is 1) and finally assign them to p, c or m.
That's how the output comes as 2 2 1.
Hope, I could make you clear.
first of all your declaration of struct is using bit fields.
struct marks{
int p:3;
int c:3;
int m:2;
};
here p:3 means we are defining P to be an int and we are preserving only 3 bit of the given number. For example , You need 3 bits to represent the value 5, which would be represented as 101. The lower 2 bits are the value 1. That's why you get m=1.
This link will give you more explanation.
Thanks.

why does '%d' not return the right value?

int a = 31;
int b = 1;
while (a)
{
b = (2 * b) + 1;
a--;
};
printf("count:%d \n", b);
it prints the right number when a is smaller than 31. Starting from 31, it just prints -1 and I don't understand why. How can I fix it?
The integer overflows and will become negative.
To fix this, you can change the int variable b to long.
long b = 1;
In the two's complement internal representation of type int if its size is equl to 4 bytes the sign bit is equal to 2^31.
Thus then you multiply b by two when b is equal to INT_MAX then the sign bit is set and the number is converted to -1.
That is while the sign bit is not set you get poistive numbers 1, 3, 7, 15 and so on. As soon as the sign bit is set you get negative number -1 that has internal representation with all bits including the sign bit are set.
The while loop is terminated when a becomes 0, since the condition
while (a) ...
evaluating to
while (a != 0)...
It will happen after the loop is executed 31 times with the following expression in it:
b = (2 * b) + 1;
while the initial value of b is 1. It will generate the series: 1, 3, 7, 15... 2^(k+1)-1, while k is the iteration number (starting from 0 for initial value). So for k=31 the value would be 2^32-1. 2^32 is overflowing the 4-byte integer storage type, which is resulting in an undefined behavior. But some compilers are usually handling the overflow by just throwing away the overflowed leftmost bits, so the truncated 2^32 is becoming 0. So 0-1 = -1 and this is your result. But again, no standard is guaranteeing that you will get this result, so you should never rely on it.
To fix it, you can use a bigger storage type, like long, and use %ld for printf.
It's ok the #EugeneSh. answer, but the series don't start in 1, but 3. And to print all values of b, the printf needs to stay into the while loop.If the intention were starting in 1, the printf needs to be the first line into the while loop.

Format Specifies in C for float datatype

int main()
{
system("color FC");
const float i=23.1234234;
printf("%5.4f",i);
getch();
return 0;
}
In above code , while printing float data type %5.4 format specifier is used.
I understood that .4 is used to get four numbers after decimal but whats the use of 5 before .4
The 5 is the length specifier. In this case, the printed float will take up at least 5 spaces. If it is shorter than that, leading spaces will be used.
(Though because of the precision 4, it will always be at least 6 characters long; the length modifier 5 in this case is a no-op.)
See documentation.
5 is used to right justify the output by 5 places i.e. the last digit will occur 5 places from cursor's initial position, if possible.
It is effective only when the length ( including the decimal ) is smaller than what is mentioned in the specifier.
e.g. printf("%5.4f",i);
till the specifier at the place of 5 is smaller than or equal than the length of the output
i.e 2(before decimal) + 4(after decimal, as chosen ) + 1 (the decimal itself) =7 , it has
no effect.
It will have effect here if it is at least 8.
At 7 it does what it should but you won's see any spaces.
5 is used to right justify the output by 5 places. Since the output is 10 character long so the effect is not seen. Now try this
#include <stdio.h>
int main()
{
const float i=23.1234234;
printf("%f\n",i);
printf("%5.4f\n",i);
printf("%7.4f\n",i);
printf("%10.4f\n",i);
printf("%12.5f",i);
return 0;
}
Output:
23.1234234
23.1234
23.1234
23.1234
23.1234

Resources