two complement encoding negative value - c

while reading the book Computer System a programmer perspective.I have found that if i take most negative value in the range of a data type for example :
char a = -128;
a = - a;
The variable a will still have the value -128 and i understand that but when i do
char a = 50;
char b = -128;
char r = a - b;
It give me the correct result -78, why is that?? it because the automatic promotion to int or there is a hardware subtraction without needing to calculate two complement of -128??

char a = -128; means char a = 0x80;, so at the promotion to int it will be 0xFFFFFF80.
-0xFFFFFF80 = 0x00000080 and that is casted to an char 0x80 which is the same as the start value.
char a = -128;
char b = 50;
char r = a - b;
0xFFFFFF80
0xFFFFFFCE
=
0xFFFFFF4E
so 4E will be written in r, which is +78.
live demo: https://ideone.com/sjyBOa

Related

C How do XOR between unsigned int pointers

I have two unsigned int pointers with 32 bit and I want do an XOR operation between these unsigned pointers.
char* a = "01110011011100100110111101000011";
char* b = "10111001100011001010010110111101";
unsigned* au = (unsigned*) a;
unsigned* bu = (unsigned*) b;
unsigned* cu = a ^ b;
Error is:
invalid operands to binary ^ (have ‘unsigned int *’ and ‘unsigned int *’)
You have strings, not unsigned integers. You'll need to convert them to unsigned integers before you can do bitwise operations on them:
char* a = "01110011011100100110111101000011";
char* b = "10111001100011001010010110111101";
unsigned au = strtoul(a, 0, 2);
unsigned bu = strtoul(b, 0, 2);
unsigned cu = a ^ b;
Your code needs to work a little harder to pull that off.
Iterate over the strings.
Pull the numbers from the digits.
Perform an XOR between the numbers.
Convert the number to a digit.
Add the resultant digit to the output.
char str1[] = "01110011011100100110111101000011";
char str2[] = "10111001100011001010010110111101";
char* p1 = str1;
char* p2 = str2;
for ( ; *p1 != '\0' && *p2 != '\0'; ++p1, ++p2 )
{
unsigned int n1 = *p1 - '0';
unsigned int n2 = *p2 - '0';
unsigned int n = n1 ^ n2;
char c = n + '0';
// Now you can change either a or be to contain the output.
*p1 = c;
}
// At this point, str1 should contain a string that looks like you performed an XOR between str1 and str2.

Convert unsigned char in C to MatLab

I am trying to convert unsigned char in C to matlab code, the vector of unsigned char is filled with hexadecimal values. Below the C code:
int main()
{
unsigned char value = 0xaa;
signed char temp;
// cast to signed value
temp = (signed char) value;
// if MSB is 1, then this will signed extend and fill the temp variable with 1's
temp = temp >> 7;
// AND with the reduction variable
temp = temp & 0x1b;
// finally shift and reduce the value
printf("%u",((value << 1)^temp));
}
The Matlab function that I create to do the same thing:
value = '0xaa';
temp = int8(value);
temp2 = int8(value);
temp = bitsra(temp,7);
temp = and(temp,'0x1b');
galois_value = xor(bitsll(temp2,1),temp);
disp(galois_value);
The values printed are different in each code, someone knows what is happening?
You have created a string:
value = '0xaa';
Of 4 characters, ['0' 'x' 'a' 'a'].
In MATLAB you don't generally handle variables bit wise, but if you want, try:
temp = int8(hex2dec('aa'));

casting unsigned char to char would result in different binary representations?

I think the title is pretty self explanatory but basically what I'm saying is that, if I have the following instruction:
a = (char) b;
knowing that a's type is char and b's is unsigned char, can that instruction result in making a and b have different binary representations?
The type char can be either signed or unsigned. Char types have no padding, so all bits are value bits.
If char is unsigned, then the value bits of a will be the same as those of b.
If char is signed, then...
if the value of b is representable by char, the common value bits of a and b will the same.
otherwise, the conversion from unrepresentable unsigned char value to char results in an implementation-defined result.
The answer in general, is no, there is no difference. Here you can test it yourself. Just supply the respective values for 'a' and 'b'
#include <stdio.h>
#include <string.h>
const char *byte_to_binary(int x)
{
static char b[9];
b[0] = '\0';
int z;
for (z = 128; z > 0; z >>= 1)
strcat(b, ((x & z) == z) ? "1" : "0");
}
return b;
}
int main(void) {
unsigned char b = -7;
char a = -7;
printf("1. %s\n", byte_to_binary(a));
a = (char) b;
printf("2. %s\n", byte_to_binary(a));
return 0;
}

Copying Ascii Value to int

I have code snippet as Below
unsigned char p = 0;
unsigned char t[4] = {'a','b','c','d'};
unsigned int m = 0;
for(p=0;p<4;p++)
{
m |= t[p];
printf("%c",m);
m = m << 2;
}
Can anybody help me in solving this. consider i have an ascii value abcd stored in an array t[]. I want to store the same value in 'm'. m is my unsigned int variable . which stores the major number. when i copy the array into m & print m . m should print abcd. can anybody state their logic.
As I understand you, you want to encode the 4 characters into a single int.
Your bit shifting is not correct. You need to shift by 8 bits rather than 2. You also need to perform the shifting before the bitwise or. Otherwise you shift too far.
And it makes more sense, in my view, to print the character rather than m.
#include <stdio.h>
int main(void)
{
const unsigned char t[4] = {'a','b','c','d'};
unsigned int m = 0;
for(int p=0;p<4;p++)
{
m = (m << 8) | t[p];
printf("%c", t[p]);
}
printf("\n%x", m);
return 0;
}
Why not just look at the t array as an unsigned int?:
unsigned int m = *(unsigned int*)t;
Or you could use an union for nice access to the same memory block in two different ways, which I think is better than shifting bits manually.
Below is an union example. With unions, both the t char array and the unsigned int are stored in the same memory blob. You get a nice interface to each, and it lets the compiler do the bit shifting (more portable, I guess):
#include <stdio.h>
typedef union {
unsigned char t[4];
unsigned int m;
} blob;
int main()
{
blob b;
b.t[0]='a';
b.t[1]='b';
b.t[2]='c';
b.t[3]='d';
unsigned int m=b.m; /* m holds the value of blob b */
printf("%u\n",m); /* this is the t array looked at as if it were an unsignd int */
unsigned int n=m; /* copy the unsigned int to another one */
blob c;
c.m=n; /* copy that to a different blob */
int i;
for(i=0;i<4;i++)
printf("%c\n",c.t[i]); /* even after copying it as an int, you can still look at it as a char array, if you put it into the blob union -- no manual bit manipulation*/
printf("%lu\n", sizeof(c)); /* the blob has the bytesize of an int */
return 0;
}
Simply assign t[p] to m.
m = t[p];
this will implicitly promote char to unsigned int.
unsigned char p = 0;
unsigned char t[4] = {'a','b','c','d'};
unsigned int m = 0;
for(p=0;p<4;p++)
{
m = t[p];
printf("%c",m);
}

integer arithmetic on pointers in C

Will the statement below calculate the length of the array???:
UART1_BUF[1] = (unsigned char)(lcl_ptr - (unsigned char *)&UART1_BUF[1]);
/////////////////////////////////////////////////////////////////////////////////////
unsigned char UART1_BUF[128];
void apple_Build_SetFIDTokenValues(void)
/* apple_Build_SetFIDTokenValues -
*
* This function builds the apple protocol StartIDPS() command.
*/
{
unsigned char * lcl_ptr;
UART1_BUF[0] = BT_START_OF_PACKET;
UART1_BUF[1] = 0x00;
//BundleSeedIDPrefToken
lcl_ptr = apple_Build_BundleSeedIDPrefToken(&UART1_BUF[1]);
UART1_BUF[1] = (unsigned char)(lcl_ptr - (unsigned char *)&UART1_BUF[1]);
*lcl_ptr = apple_checksum((unsigned char *)UART1_BUF, UART1_BUF[1]);
UART1_BUF[UART1_BUF[1]] = *lcl_ptr;
}
unsigned char * apple_Build_BundleSeedIDPrefToken(unsigned char *buf_ptr)
{
*(buf_ptr++) = 0x0D; //length of BundleSeedIDPrefToken minus this byte
*(buf_ptr++) = BundleSeedIDPref_Token_FID_TYPE;
*(buf_ptr++) = BundleSeedIDPref_Token_FID_SUBTYPE;
//BundleSeedIDString
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
return (buf_ptr);
}
Yes, provided that the result fits in a byte - which, from the code sample, it will - and, by 'length of the array', you mean the number of bytes minus the packet header.
It will give you the number of bytes added by the apple_Build_BundleSeedIDPrefToken() function. (The total number of bytes that have been filled in the UART_BUF[] array is one more than that, because that statement won't count the byte at UART_BUF[0].)
In general, subtracting two pointers of type T * into an array of elements of type T gives you the difference as the number of elements (rather than the number of bytes). (The result is undefined if either of the two pointers do not point to either an element within the same array, or the element just past the last one.) The result itself has a signed integer type, ptrdiff_t, which is defined in <stddef.h>.
However, here, both pointers are pointing into the same array of unsigned char, so each element is a byte by definition.
So, the expression lcl_ptr - (unsigned char *)&UART1_BUF[1] will give the number of bytes added by the function. (Note that &UART_BUF[1] is of type unsigned char * already, so the cast inside the expression is unnecessary.)
That expression is then cast to unsigned char, which could in theory truncate the result, although it clearly doesn't in the above example.
I note that the code is a little odd, in that it assigns to UART_BUF[1] three times!
UART1_BUF[1] = 0x00; sets it to 0;
lcl_ptr = apple_Build_BundleSeedIDPrefToken(&UART1_BUF[1]); sets it to 0x0D inside the called function;
UART1_BUF[1] = (unsigned char)(lcl_ptr - (unsigned char *)&UART1_BUF[1]); sets it to 0x0E, as the function adds 14 bytes.
More generally, remember to be careful with pointer subtractions: expecting them to always give a number of bytes is a common mistake...
#include <stdio.h>
#include <stddef.h>
int main(void)
{
int array[4];
int *start, *end;
start = &array[1];
end = &array[3];
printf("Difference (as int *): %d\n", end - start);
printf("Difference (as char *): %d\n", (char *)end - (char *)start);
return 0;
}
gives (on a system where sizeof(int)==4):
Difference (as int *): 2
Difference (as char *): 8

Resources