Why C programming gives different output? [duplicate] - c

This question already has answers here:
How does C Handle Integer Literals with Leading Zeros, and What About atoi?
(8 answers)
Closed 3 years ago.
I got unexpected outputs, and I could not figure out the reason.
#include <stdio.h>
int main() {
int a = 0100;
int b = 010;
int c = 1111;
int d = 01111;
printf("0100 => %d, 010 => %d, 1111 => %d, 01111=> %d\n", a, b, c, d);
}
Output:
0100 => 64, 010 => 8, 1111 => 1111, 01111=> 585
Why does such output occur?

In C, putting either 0x or 0 before an integer literal value will cause the compiler to interpret the number in base 16 (hexadecimal) and base 8 (octal), respectively.
Normally, we interpret and read numbers in base 10 (decimal). However, we sometimes will use these other bases because they are useful powers of 2 that can represent groups of bits (1 hexadecimal digit = 4 bits, 1 octal digit = 3 bits), and bit manipulation is something that C wants to provide. This is why you'll see something like char be represented with 2 hexadecimal digits (e.g. 0x12) to set a single char to be a specific bit sequence.
If you wanted to verify this, printf also allows you to output int in hexadecimal and octal as well using %x and %o respectively instead of %d.
#include <stdio.h>
int main()
{
int a = 0100;
int b = 010;
int c = 1111;
int d = 01111;
printf("0100 => %o, 010 => %o, 1111 => %d, 01111=> %o\n", a,b,c,d);
}
If you run this program, you'll get the following:
gcc -ansi -O2 -Wall main.c && ./a.out
0100 => 100, 010 => 10, 1111 => 1111, 01111=> 1111
...which is exactly what you set the values to in the program, just without the prefixes. You just mistakenly used another integer encoding by accident on assignment in the original code, and used a different one to output the value.

0 prefix gives you octal, and you tried to print decimal.

Related

Bitwise operations in C yields unwanted 1's or F's [duplicate]

This question already has answers here:
Right shifting negative numbers in C
(6 answers)
Closed 9 months ago.
I have a problem with C's bitwise operations and can't "merge" two numbers together.
Suppose I have the number 0x0A (or any 2 hexadecimal digits) and I want to replace the left digit with 0xF for example, That is:
00001010 -> 11111010 in terms of bitwise.
What I tried to do is the following:
We drop the left digit of the 2-digit hex number by left shifting (sizeof(int)*8-4) times, thus leaving the rightmost bits that we care about, and then right shifting (unsigned) so that we get only the right hex digit in the end. In the example above it won't matter as it'll yield 'A' which is the same as 0x0A.
The second step is to "merge" the digit we got in step one and the shifted hex digit we want to use, and we'll do that by using an OR gate.
Thus:
Hex number before and after step one: A (1010)
Desired hex digit after shifting: F0 (1111 0000)
OR gate:
00001010
OR 11110000
= 11111010 = 0xFA
However, for some reason, my C code does all of the above correctly, and just when applying OR it gives the result 0xFFFFFFFA (8-byte).
Is there something that I'm missing on how C works with bitwise?
Note that I use sizeof(int) because the code should be able to account for 4 or 8 byte int.
Thanks for help in advance!
int setHexDigit(char* digitPairPtr, int digitPos, char hexDigit)
{
int return_value = 0;
if( (hexDigit>='0' && hexDigit<='9') || (hexDigit>='A' && hexDigit <='F'))
{
if(digitPos==0)
{
hexDigit = ((hexDigit<='9' && hexDigit>='0') ? (hexDigit-'0') : ( (hexDigit>='A' && hexDigit<='F') ? (hexDigit-('A'-10)) : (-1))); //THIS LINE IS NOT IMPORTANT
*digitPairPtr = ((unsigned)*digitPairPtr<<((sizeof(int))*8-4))>>((sizeof(int))*8-4); //Drop left digit.
hexDigit = (hexDigit << 4);
*digitPairPtr = *digitPairPtr | hexDigit;
return_value=1;
}
else
{
//For later
}
}
return return_value;
}
int main()
{
char c = 0x0A;
setHexDigit(&c,0,'F');
printf("\n%X", c);
return 0;
}
I think the problem is in the printf statement. If you are using a compiler where char is signed, passing c to printf will sign extend it from 0xFA to 0xFFFFFFFA. Try using unsigned char instead.

How to create a negative binary number using signed/unsigned in C?

My thoughts: if one declares an int it basically gets an unsigned int. So if I need a negative value I have to explicitly create a signed int.
I tried
int a = 0b10000101;
printf("%d", a); // i get 138 ,what i've expected
signed int b = 0b10000101; // here i expect -10, but i also get 138
printf("%d", b); // also tried %u
So am I wrong that an signed integer in binary is a negative value?
How can I create a negative value in binary format?
Edit Even if I use 16/32/64 bits I get the same result. unsigned/signed doest seems to make a difference without manually shifting the bits.
If numbers are represented as two's complement you just need to have the sign bit set to ensure that the number is negative. That's the MSB. If an int is 32 bits, then 0b11111111111111111111111111111111 is -1, and 0b10000000000000000000000000000000 is INT_MIN.
To adjust for the size int(8|16|64)_t, just change the number of bits. The sign bit is still the MSB.
Keep in mind that, depending on your target, int could be 2 or 4 bytes. This means that int a=0b10000101 is not nearly enough bits to set the sign bit.
If your int is 4 bytes, you need 0b10000000 0000000 0000000 00000000 (spaces added for clarity).
For example on a 32-bit target:
int b = 0b11111111111111111111111111111110;
printf("%d\n", b); // prints -2
because int a = 0b10000101 has only 8 bits, where you need 16 or 32. Try thi:
int a = 0b10000000000000000000000000000101
that should create negative number if your machine is 32bits. If this does not work try:
int a = 0b1000000000000101
there are other ways to produce negative numbers:
int a = 0b1 << 31 + 0b101
or if you have 16 bit system
int a = 0b1 << 15 + 0b101
or this one would work for both 32 or 16 bits
int a = ~0b0 * 0b101
or this is another one that would work on both if you want to get -5
int a = ~0b101 + 1
so 0b101 is 5 in binary, ~0b101 gives -6 so to get -5 you add 1
EDIT:
Since I now see that you have confusion of what signed and unsigned numbers are, I will try to explain it as simple as possible int
So when you have:
int a = 5;
is the same as:
signed int a = 5;
and both of them would be positive. Now it would be the same as:
unsigned int a = 5;
because 5 is positive number.
On the other hand if you have:
int a = -5;
this would be the same as
signed int a = -5;
but it would not be the same as following:
unsigned int a = -5;
the first 2 would be -5, the third one is not the same. In fact it would be the same if you entered 4294967291 because they are the same in binary form but the fact that you have unsigned in front means that compiler would store it the same way but treat it as positive value.
How to create a negative binary number using signed/unsigned in C?
Simply negate the constant of a positive value. To attempt to do so with many 1's
... 1110110 assumes a bit width for int. Better to be portable.
#include <stdio.h>
int main(void) {
#define NEGATIVE_BINARY_NUMBER (-0b1010)
printf("%d\n", NEGATIVE_BINARY_NUMBER);
}
Output
-10

Multiply two 8 bit numbers

I am trying to multiply two 8 bit numbers ans store the 16 bit result in two 8 bit variables, Eg :
91*16 = 1456
High = 14 and Low = 56
This is the code I'm using but not getting desired result . Can someone point out my error please?
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include<time.h>
int main()
{
uint8_t a = 91;
uint8_t b = 16;
uint16_t c = a*b;
printf("Value at c is %d \n",c);
uint8_t lo = c & 0x00FF;
uint8_t hi = c >> 8;
printf("Hi and lo value are %d and %d \n",hi,lo);
return 0;
}
I get Hi = 5 and Lo = 176, why is it so ?
Result of a*b is
0000 0101 1011 0000
( 5 )( 176 )
That is what you printed.
You mixed up decimal representation with others. The value you see is not stored like 0001 0100 0101 0110. If it was, then yes you would get your desired result (But it is debatable how helpful it would be).
To get what you want, you might consider using c%100 and c/100.(You are getting the most significant 2 digits in hi and rest two digits in lo).
uint8_t lo = c %100;
uint8_t hi = c /100;
And print them properly
printf("%" PRIu8 "\n", lo); //56
printf("%" PRIu8 "\n", hi); //14
In this way to be precise printf("Hi and lo value are %" PRIu8" and %"PRIu8" \n",hi,lo);.
Note that any 2 digit positive integer can be placed in uint8_t but to be more generic, you might want to consider that sometimes the resultant multiplication can be of 5 decimal digits.
If you want decimal representation (which doesn't make sense as decimal does not evenly divide byte values) you need to use /100 and %100 instead of bitwise operations.

The Powers of 10

#include <stdio.h>
#include <stdlib.h>
#define SIZEOF(arr) (sizeof(arr) / sizeof(arr[0]))
#define PrintInt(expr) printf("%s:%d\n",#expr,(expr))
int main()
{
/* The powers of 10 */
int pot[] = {
0001,
0010,
0100,
1000
};
int i;
for(i=0;i<SIZEOF(pot);i++)
PrintInt(pot[i]);
return 0;
}
The output of the following code is
pot[i]:1
pot[i]:8
pot[i]:64
pot[i]:1000
why does it give such output??`
Prefixing a numeric literal in C with a 0 digit will output it in Octal, which is a base 8 numeric system.
Oct(1) = Dec(1)
Oct(10) = Dec(8)
Oct(100) = Dec(64)
That's where your numbers are coming from.
FYI, Hexadecimal literals are prefixed with 0x and binary literals are prefixed with 0b (IIRC)
Edit: To actually answer your question, just remove the leading zeroes from the numbers and it should give you the desired output.
Number literals which start with a zero are interpreted as being in octal – base 8. So the first three numbers are octal 1, 10 and 100 (which are 1, 8 and 64 in base-10); the last number is base 10.
Based on how your constants are defined, and how your question is worded, I think you want hex. Prefix your values with "0x":
int pot[] = {
0x0001,
0x0010,
0x0100,
0x1000
;

How is this bitwise AND operator masking the lower seven order bits of the number?

I am reading The C Programming Language by Brian Kernigan and Dennis Ritchie. Here is what it says about the bitwise AND operator:
The bitwise AND operator & is often used to mask off some set of bits, for example,
n = n & 0177
sets to zero all but the low order 7 bits of n.
I don't quite see how it is masking the lower seven order bits of n. Please can somebody clarify?
The number 0177 is an octal number representing the binary pattern below:
0000000001111111
When you AND it using the bitwise operation &, the result keeps the bits of the original only in the bits that are set to 1 in the "mask"; all other bits become zero. This is because "AND" follows this rule:
X & 0 -> 0 for any value of X
X & 1 -> X for any value of X
For example, if you AND 0177 and 0545454, you get
0000000001111111 -- 0000177
0101010101010101 -- 0545454
---------------- -------
0000000001010101 -- 0000154
In C an integer literal prefixed with 0 is an octal number so 0177 is an octal number.
Each octal digit (of value 0 to 7) is represented with 3 bits and 7 is the greatest value for each digit. So a value of 7 in octal means 3 bits set.
Since 0177 is an octal literal and each octal number is 3 three bits you have, the following binary equivalents:
7 = 111
1 = 001
Which means 0177 is 001111111 in binary.
It is already explained that the first '0' used for octal representation of a number in ANSI C. Actually, the number 0177 (octal) is same with 127 (in decimal), which is 128-1 and also can be represented as 2^7-1, and 2^n-1 in binary representation means take n 1's and put all the 1's to the right.
0177 = 127 = 128-1
which is a bitmask;
0000000000000000000000001111111
You can check the code down below;
Demo
#include <stdio.h>
int main()
{
int n = 0177; // octal representation of 127
printf("Decimal:[%d] : Octal:[%o]\n", n, n, n);
n = 127; // decimal representation of 127
printf("Decimal:[%d] : Octal:[%o]\n", n, n, n);
return 0;
}
Output
Decimal:[127] : Octal:[177]
Decimal:[127] : Octal:[177]
0177 is an octal value each digit is represented by 3 bits form the value 000 to 111 so 0177 translates to 001111111 (i.e 001|111|111) which if you consider in 32 bit binary ( can be 64 bit too except the remainder of the digits are populated as per the MSB i.e sign bit in this case value 0) form is 0000000000000000000000001111111 and and performing a bitwise with it for a given number, will output the lower 7 bits of the number turning of rest of the digits in the n-bit number to 0.
(since x&0 =0 & x&1=x e.g 0&0=0 ,1&0=0, 1&1=1 0&1=1)

Resources