Getting a double word from binary data - c

char * data = 0xFF000010FFFFFFFFFFFFFFFFFFFFFFFFFFF;
I want to get DOUBLE WORD in data[1] (0x00000010) and store it in var int i.
Would this do the trick?
int i = (int) data[1]+data[2]+data[3]+data[4]

You are attempting to just add four bytes rather than position the values into the correct part of the integer. Without specifying the endianness of your platform, it's not possible to provide a final answer.
The general approach is to place each byte in the correct position of the int, something like this:
int i = 256 * 256 * 256 * data[0] + 256 * 256 * data[1] + 256 * data[2] + data[3]
(big endian example)
Note that the indices are 0-based, not 1-based as in your example. The "base" in this example is 256 because each byte can represent 256 values.
To understand why this is so, consider the decimal number
5234
You can re-write that as:
5000 + 200 + 30 + 4
or 10 * 10 * 10 * 5 + 10 * 10 * 2 + 10 * 3 + 4
As you process data for each digit, you multiply the value by the-number-base-to-the-power-of-the-digit-position (rightmost digit for base 10 is 10^0, then 10^1, 10^2, etc).

You must convert from your string into the actual data. Consider using atol() or something similar to get the value in memory, then worry about editing it.

Related

Calculating a 16 bit checksum?

Working with a program in c that reads in a file and then I have to do both 8 bit and 16 bit checksum for a program.I only have 8 bit checksum done so far.
This is what I understand
I read the file and store the information in an array of characters and at end it takes the newline feed. so for example to calculate 8 bit check sum this is what happens essentially
File has 3 letters total ( 3 a's and a newline feed)
so array holds 4 chars aaa+(newline) (97+97+97+10)
To my understanding I add all the bytes in the array then do % 256 and that is my checksum.
97 * 3 = //3 a's (small a ) pulled from ascii table from what I understand
291 + 10 = 301 // + newline
301 % 256 = cc in hex //
however I am getting confused on how to calculate the 16 bit checksum because I can't add 2 characters at a time if its a single character array?
any help would be greatly appreciated
To calculate a 16-bit checksum, you process the array in increments of 2, and put one byte into the low-order byte of the value that you're adding, and the other byte into the high-order byte.
uint8_t array[MAX]; // The data gets copied into here
size_t length; // This is the length of the data
uint16_t checksum = 0;
size_t even_length = length - length%2; // Round down to multiple of 2
for (int i = 0; i < even_length; i += 2) {
uint16_t val = array[i] + 256 * array[i+1];
checksum += val;
}
if (i < length) { // Last byte if it's odd length
checksum += array[i];
}
There's no need to use modulus, since unsigned integers implement modular arithmetic automatically.

Get bits from number string

If I have a number string (char array), one digit is one char, resulting in that the space for a four digit number is 5 bytes, including the null termination.
unsigned char num[] ="1024";
printf("%d", sizeof(num)); // 5
However, 1024 can be written as
unsigned char binaryNum[2];
binaryNum[0] = 0b00000100;
binaryNum[1] = 0b00000000;
How can the conversion from string to binary be made effectively?
In my program i would work with ≈30 digit numbers, so the space gain would be big.
My goal is to create datapackets to be sent over UDP/TCP.
I would prefer not to use libraries for this task, since the available space the code can take up is small.
EDIT:
Thanks for quick response.
char num = 0b0000 0100 // "4"
--------------------------
char num = 0b0001 1000 // "24"
-----------------------------
char num[2];
num[0] = 0b00000100;
num[1] = 0b00000000;
// num now contains 1024
I would need ≈ 10 bytes to contain my number in binary form. So, if I as suggested parse the digits one by one, starting from the back, how would that build up to the final big binary number?
In general, converting a number in string representation to decimal is easy because each character can be parsed separately. E.g. to convert "1024" to 1024 you can just look at the '4', convert it to 4, multiply by 10, then convert the 2 and add it, multiply by 10, and so on until you have parsed the whole string.
For binary it is not so easy, e.g. you can convert 4 to 100 and 2 to 010 but 42 is not 100 010 or 110 or something like that. So, your best bet is to convert the whole thing to a number and then convert that number to binary using mathematical operations (bit shifts and such). This will work fine for numbers that fit in one of the C++ number types, but if you want to handle arbitrarily large numbers you will need a BigInteger class which seems to be a problem for you since the code has to be small.
From your question I gather that you want to compress the string representation in order to transmit the number over a network, so I am offering a solution that does not strictly convert to binary but will still use fewer bytes than the string representation and is easy to use. It is based on the fact that you can store a number 0..9 in 4 bits, and so you can fit two of those numbers in a byte. Hence you can store an n-digit number in n/2 bytes. The algorithm could be as follows:
Take the last character, '4'
Subtract '0' to get 4 (i.e. an int with value 4).
Strip the last character.
Repeat to get 0
Concatenate into a single byte: digits[0] = (4 << 4) + 0.
Do the same for the next two numbers: digits[1] = (2 << 4) + 1.
Your representation in memory will now look like
4 0 2 1
0100 0000 0010 0001
digits[0] digits[1]
i.e.
digits = { 64, 33 }
This is not quite the binary representation of 1024, but it is shorter and it allows you to easily recover the original number by reversing the algorithm.
You even have 5 values left that you don't use for storing digits (i.e. everything larger than 1010) which you can use for other things like storing the sign, decimal point, byte order or end-of-number delimiter).
I trust that you will be able to implement this, should you choose to use it.
If I understand your question correctly, you would want to do this:
Convert your string representation into an integer.
Convert the integer into binary representation.
For step 1:
You could loop through the string
Subtract '0' from the char
Multiply by 10^n (depending on the position) and add to a sum.
For step 2 (for int x), in general:
x%2 gives you the least-significant-bit (LSB).
x /= 2 "removes" the LSB.
For example, take x = 6.
x%2 = 0 (LSB), x /= 2 -> x becomes 3
x%2 = 1, x /= 2 -> x becomes 1
x%2 = 1 (MSB), x /= 2 -> x becomes 0.
So we we see that (6)decimal == (110)bin.
On to the implementation (for N=2, where N is maximum number of bytes):
int x = 1024;
int n=-1, p=0, p_=0, i=0, ex=1; //you can use smaller types of int for this if you are strict on memory usage
unsigned char num[N] = {0};
for (p=0; p<(N*8); p++,p_++) {
if (p%8 == 0) { n++; p_=0; } //for every 8bits, 1) store the new result in the next element in the array. 2) reset the placing (start at 2^0 again).
for (i=0; i<p_; i++) ex *= 2; //ex = pow(2,p_); without using math.h library
num[n] += ex * (x%2); //add (2^p_ x LSB) to num[n]
x /= 2; // "remove" the last bit to check for the next.
ex = 1; // reset the exponent
}
We can check the result for x = 1024:
for (i=0; i<N; i++)
printf("num[%d] = %d\n", i, num[i]); //num[0] = 0 (0b00000000), num[1] = 4 (0b00000100)
To convert a up-to 30 digit decimal number, represented as a string, into a serious of bytes, effectively a base-256 representation, takes up to 13 bytes. (ceiling of 30/log10(256))
Simple algorithm
dest = 0
for each digit of the string (starting with most significant)
dest *= 10
dest += digit
As C code
#define STR_DEC_TO_BIN_N 13
unsigned char *str_dec_to_bin(unsigned char dest[STR_DEC_TO_BIN_N], const char *src) {
// dest[] = 0
memset(dest, 0, STR_DEC_TO_BIN_N);
// for each digit ...
while (isdigit((unsigned char) *src)) {
// dest[] = 10*dest[] + *src
// with dest[0] as the most significant digit
int sum = *src - '0';
for (int i = STR_DEC_TO_BIN_N - 1; i >= 0; i--) {
sum += dest[i]*10;
dest[i] = sum % 256;
sum /= 256;
}
// If sum is non-zero, it means dest[] overflowed
if (sum) {
return NULL;
}
}
// If stopped on something other than the null character ....
if (*src) {
return NULL;
}
return dest;
}

How to store 999 value in character data type

In one of the interview. A person asked I want to store 999 value in character data type. How to do it?
999 = 1111100111 (In binary representation)
character is of type 1 byte. 8bits.
int main()
{
int a =999;
signed char c = 999;
printf("%d %d",a,c);
}
when I compile the program I get the warning as
storeintinchar.c:6:1: warning: overflow in implicit constant conversion [-Woverflow]
when I run it:
a=999. c=-25;
when I change character to unsigned char c=999;
when I compile the program I get the warning as
storeintinchar.c:6:1: warning: large integer implicitly truncated to unsigned type [-Woverflow]
when I run it.
a=999. c=231;
Can we store 999 value in character is it possible in any way to do that.
What was interviewer trying to test?
Is it possible to store 999 value in wchar_t. When I am searching for above question I found in GNU C Library wchar_t is always 32 bits wide. Then we can use it. Is it works
int main()
{
int a =999;
unsigned char c = 999;
wchar_t d=999;
printf("%d %d %d",a,c,d);
}
output: 999 231 999
wchar_t is 4 bytes. I was able to store 999 value in it.
I am thankful for all the people part of stackoverflow providing quick results and giving reasonable answers.
You can theoretically store 999 in one byte if the compiler has proper byte size. Check limits.h for size of your current char type. But of course you can't expect such size of charfor every architecture and every compiler. Usually for modern architectures one char is 8 bits and you just can't store there such a big number without any additional memory used.
You can store 999 (and also some other numbers), however you will need to implement an algorithm which sort of "compresses" the number, with the outcome that the bits of the char do not mean what they usually, but are holding a key to the solution ... the algorithm is like:
bit idx: 7 6 5 4 3 2 1 0
bit value: 0 0 0 0 0 1 1 1
So, for this to be 999 you do:
999 = bit[0] * 9 * (10 ^ 0) + // 1 * 9 +
bit[1] * 9 * (10 ^ 1) + // 1 * 90 +
bit[2] * 9 * (10 ^ 2) + // 1 * 900
bit[3] * 9 * (10 ^ 3) + // 0 * 9000 ....
....
You cannot. A char data type (on every platform you are likely to come across) has 8 bits, and thus can encode a maximum of 256 values. Assuming you need all the values up to 999, that's more than it can encode. As a char is signed, it stores values only between -128 and +127.
However, if you only need to encode some of the values up to and including 999, you could use a look up table.
Alternatively, you could use (e.g.) 2 char values, sandwiched together to make a 16 bit integer, which could store unsigned numbers up to 65535.
To store the value 999 in char data, you need to break it up and store it in 2 or more chars. For example (using 7 bits of each char):
char first = 999 % 128
char second = 999 / 128
Also note that it's possible for a char to represent any value. For example, you could say that the value 1 represents 999, and then only store 1. This is different to being able to store a value.

c: bit reversal logic

I was looking at the below bit reversal code and just wondering how does one come up with these kind of things. (source : http://www.cl.cam.ac.uk/~am21/hakmemc.html)
/* reverse 8 bits (Schroeppel) */
unsigned reverse_8bits(unsigned41 a) {
return ((a * 0x000202020202) /* 5 copies in 40 bits */
& 0x010884422010) /* where bits coincide with reverse repeated base 2^10 */
/* PDP-10: 041(6 bits):020420420020(35 bits) */
% 1023; /* casting out 2^10 - 1's */
}
Can someone explain what does comment "where bits coincide with reverse repeated base 2^10" mean?
Also how does "%1023" pull out the relevent bits? Is there any general idea in this?
It is a very broad question you are asking.
Here is an explanation of what % 1023 might be about: you know how computing n % 9 is like summing the digits of the base-10 representation of n? For instance, 52 % 9 = 7 = 5 + 2.
The code in your question is doing the same thing with 1023 = 1024 - 1 instead of 9 = 10 - 1. It is using the operation % 1023 to gather multiple results that have been computed “independently” as 10-bit slices of a large number.
And this is the beginning of a clue as to how the constants 0x000202020202 and 0x010884422010 are chosen: they make wide integer operations operate as independent simpler operations on 10-bit slices of a large number.
Expanding on Pascal Cuoq idea, here is an explaination.
The general idea is, in any base, if any number is divided by (base-1), the remainder will be sum of all the digits in the number.
For example, 34 when divided by 9 leaves 7 as remainder. This is because 34 can be written as 3 * 10 + 4
i.e. 34 = 3 * 10 + 4
= 3 * (9 +1) + 4
= 3 * 9 + (3 +4)
Now, 9 divides 3 * 9, leaving remainder (3 + 4). This process can be extended to any base 'b', since (b^n - 1) is always divided by (b-1).
Now, coming to the problem, if a number is represented in base 1024, and if the number is divided by 1023, the remainder will be sum of its digits.
To convert a binary number to base 1024, we can group bits of 10 from the right side into single number
For example, to convert binary number 0x010884422010(0b10000100010000100010000100010000000010000) to base 1024, we can group it into 10 bits number as follows
(1) (0000100010) (0001000100) (0010001000) (0000010000) =
(0b0000000001)*1024^4 + (0b0000100010)*1024^3 + (0b0001000100)*1024^2 + (0b0010001000)*1024^1 + (0b0000010000)*1024^0
So, when this number is divided by 1023, the remainder will sum of
0b0000000001
+ 0b0000100010
+ 0b0001000100
+ 0b0010001000
+ 0b0000010000
--------------------
0b0011111111
If you observe the above digits closely, the '1' bits in each above digit occupy complementay positions. So, when added together, it should pull all the 8 bits in the original number.
So, in the above code, "a * 0x000202020202", creates 5 copies of the byte "a". When the result is ANDed with 0x010884422010, we selectively choose 8 bits in the 5 copies of "a". When "% 1023" is applied, we pull all the 8 bits.
So, how does it actually reverse bits? That is bit clever. The idea is, the "1" bit in the digit 0b0000000001 is actually aligned with MSB of the original byte. So, when you "AND" and you are actually ANDing MSB of the original byte with LSB of the magic number digit. Similary the digit 0b0000100010 is aligned with second and sixth bits from MSB and so on.
So, when you add all the digits of the magic number, the resulting number will be reverse of the original byte.

how to convert the value of int to a hexadecimal value and assign it to a variable?

I have a variable:
int a = 10;
I want to convert it to a hexadecimal value with 0x in front of 10 as: 0x10, and assign it to other variable, how to convert it?
Use snprintf():
char buf[128];
snprintf(buf, 128, "0x%d", a); // buf = "0x10"
Then read it back using sscanf():
unsigned int new_a;
if (1 == sscanf(buf, "0x%X", &new_a))
{
}
If your attempt is to reinterpret a decimal as hex, the problem means re-evaluating the polynomial A = a*10^n + b*10^(n-1) + ... + c to B=a*16^n + b*16^(n-1) + ... + c as in
1 1 2 3 = 1*1000 + 1 * 100 + 2 * 10 + 3
(0x) 1 1 2 3 = 1*4096 + 1 * 256 + 2 * 16 + 3 (=4387 dec)
Find the coefficients with repeated modulo and divide by 10, and add the results multiplied with the proper power of 16. (implements with shifting).
This is a question of representation. You can easily represent your decimal value as hex by
print("0x%x", a);
Which will print out 0xa in your particular case. For C it is insignificant if you have 0xa or 10 or 012.

Resources