Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 9 years ago.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
I'm playing around attempting to check specific bytes within a packet's payload and test if they are >,<,!, = to a specified value. The boundary points are dynamic, what is the best way to evaluate the bytes between them?
For example, I have a packet with a payload (following the headers of course) and I want to evaluate between byte 5 and byte 10 to see if it is greater than some specified value.
The return value of memcmp() does a nice unsigned little endian compare.
return memcmp(&packet[IndexLo], &Reference, IndexHi - IndexLo + 1);
A portable method would simple compare 1 byte at a time.
Quick method but has a number of assumptions:
. Packet data and platform same endian and Little.
. Boundary_width <= sizeof inttype.
. unsigned arithmetic.
. Optimized for Packet_CompareMask().
. Accessing a width integer on any byte boundary OK.
. OK to access memory just past end of packet.
typedef uint64_t inttype;
int Packet_CompareMask(const char *packet, size_t IndexLo, unint64_t Mask, inttype Reference) {
// This fails on machine with alignment restricts on wide integers.
inttype x = *((inttype *) &packet[IndexLo]);
x &= Mask;
if (x < Reference) return -1;
return x > 0;
}
int Packet_CompareRange(const void *packet, size_t IndexLo, size_t IndexHi, inttype Reference) {
inttype Mask = 0;
ssize_t Diff = IndexHi - IndexLo;
if ((Diff <= 0) || (Diff > (sizeof(Mask) - 1))) {
; // handle error
}
// This only works on little endian machines. A variant would work with Big endian.
while (--Diff >= 0) {
Mask <<= 8;
Mask |= 0xFF;
}
return Packet_CompareRange(packet, IndexLo, Mask, Reference);
}
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 months ago.
Improve this question
I have binary string( only 0s or 1s) "0101011111011111000001001001110110", for Huffman encoding I want to store each char in the string as bit representation in a uint8_t array.
If I write the binary string as-is into a file it occupies 35 bytes. If we can store each binary char in the string as bit representation in uint8_t array, it can be stored in ~5 bytes.
static uint8_t out_buffer[1024];
static uint32_t bit_pos = 0;
void printbuffer()
{
printf("Just printing bits\n");
int i;
for (i = 0; i < bit_pos; i++) {
printf("%c", (out_buffer[i / 8] & 1 << (i % 8)) ? '1' : '0');
}
}
void append_to_bit_array(char* in, int len, uint8_t* buf)
{
int i;
printbuffer();
for (i = 0; i < len; i++) {
if (in[i])
{
buf[bit_pos / 8] |= 1 << (bit_pos % 8);
}
bit_pos++;
}
}
You need to first decide on what order you want to put the bits in the bytes — i.e. put the first bit in the most significant bit of the first byte, or the least? You also need to have a strategy to deal with the extra 0 to 7 bits in the last byte. Those could look like another Huffman code, and give you extraneous symbols when decoding. Either you will need a count of symbols to decode, or you will need an end symbol that you add to your set before Huffman coding, and send that symbol at the end.
Learn the bitwise operators in C noted in your tag, and use those to place each bit, one by one, into the sequence of bytes. Those are at least the shifts << and >>, and &, and or |.
For example, 1 << n gives you a one bit in position n. a |= 1 << n would set that bit in a, given that a is initialized to zero. On the decoding end, you can use & to see if a bit is set. E.g. a & (1 << n) would be non-zero if bit n in a is set.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I want a function which would help me to extract few bits or bytes from a starting bit position from a byte array. The order of the byte array is LSB. The skeleton of the code is as follows:
typedef unsigned char uint8;
typedef unsigned short uint16;
uint16 ExtractBitsOrBytes(uint16 StartBit, uint8 *ByteArray, uint16 BitsWanted)
{
uint16 Result;
...
}
How can I implement this logic in C?. Any example or starting point is much appreciated.
Your problem is not fully specified: LSB refers to the order of bytes in memory for integral types spanning more than one byte. In your case you must specify how the bits are numbered in the array and composed to form the value extracted.
It would make sense to number the bits from 0, such that bit n is the bit with value 1 << (n % 8) in the byte at offset n / 8. For consistency, the bit with the lowest number should become the least significant bit of the extracted value. This convention is consistent with LSB as extracting 16 bits at offset 0 yields the value of the uint16 stored in the first 2 bytes of the array.
Here is a naive implementation with this convention:
typedef unsigned char uint8;
typedef unsigned short uint16;
uint16 ExtractBitsOrBytes(uint16 StartBit, const uint8 *ByteArray, uint16 BitsWanted) {
// assuming BitsWanted <= 16
uint16 result = 0;
uint16 i;
for (i = 0; i < BitsWanted; i++) {
result |= (uint16)((ByteArray[StartBit >> 3] >> (StartBit & 7)) & 1) << i;
StartBit++;
}
return result;
}
Note however that the convention used for monochrome bitmaps on many systems is different: the leftmost pixel corresponds to the most significant bit of the first byte, a convention inherited from choices made in the late 70s, mixing MSB and LSB, that made graphics software more complicated than it should have been.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am having trouble writing an algorithm for a 1byte / 8 bit checksum.
Obviously with 8bits over a decimal value of 255 the Most significant bits have to wrap around. I think I am doing it correctly.
Here is the code...
#include <stdio.h>
int main(void)
{
int check_sum = 0; //checksum
int lcheck_sum = 0; //left checksum bits
int rcheck_sum = 0; //right checksum bits
short int mask = 0x00FF; // 16 bit mask
//Create the frame - sequence number (S) and checksum 1 byte
int c;
//calculate the checksum
for (c = 0; c < length; c++)
{
check_sum = (int)buf[c] + check_sum;
printf("\n Check Sum %d ", check_sum); //debug
}
printf("\nfinal Check Sum %d", check_sum); //debug
//Take checksum and make it a 8 bit checksum
if (check_sum > 255) //if greater than 8 bits then encode bits
{
lcheck_sum = check_sum;
lcheck_sum >> 8; //shift 8 bits to the right
rcheck_sum = check_sum & mask;
check_sum = lcheck_sum + rcheck_sum;
}
//Take the complement
check_sum = ~check_sum;
//Truncate - to get rid of the 8 bits to the right and keep the 8 LSB's
check_sum = check_sum & mask;
printf("\nTruncated and complemented final Check Sum %d\n",check_sum);
return 0;
}
Short answer: you are not doing it correctly, even if the algorithm would be as your code implies (which is unlikely).
Standard warning: Do not use int if your variable might wrap (undefined behaviour) or you want to right-shift potentially negative values (implementation defined). OTOH, for unsigned types, wrapping and shifting behaviour is well defined by the standard.
Further note: Use stdint.h types if you need a specific bit-size! The built-in standard types are not guaranteed (including char) to provide such.
Normally an 8 bit checksum of an 8 bit buffer is calculated as follows:
#include <stdint.h>
uint8_t chksum8(const unsigned char *buff, size_t len)
{
unsigned int sum; // nothing gained in using smaller types!
for ( sum = 0 ; len != 0 ; len-- )
sum += *(buff++); // parenthesis not required!
return (uint8_t)sum;
}
It is not clear what you are doing with all the typecasts or shifts; uint8_t as being guaranteed the smallest (unsigned) type, the upper bits are guaranteed to be "cut off".
Just compare this and your code and you should be able to see if your code will work.
Also note that there is not the single checksum algorithm. I did not invert the result in my code, nor did I fold upper and lower bytes as you did (the latter is pretty uncommon, as it does not add much more protection).
So, you have to verify the algorithm to use. If that really requires to fold the two bytes of a 16 bit result, change sum to uint16_t` and fold the bytes as follows:
uint16_t sum;
...
// replace return with:
while ( sum > 0xFFU )
sum = (sum & 0xFFU) + ((sum >> 8) & 0xFFU);
return sum;
This cares about any overflow from adding the two bytes of sum (the loop could also be unrolled, as the overflow can only occur once).
Sometimes, CRC algorithms are called "checksum", but these are actually a very different beast (mathematically, they are the remainder of a binary polynomial division) and require much more processing (either at run-time, or to generate a lookup-table). OTOH, CRCs provide a much better detection of data corruption - but not to manipulation.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this question
I am trying to implement a CRC32 algorithm in C that does not use a look up table (I need to use it in a boot loader that doesn't have enough memory available to have one). Is there an available solution to this that has a public license?
A quick search harvested this webpage. I wasn't able to find the license for these code snippets.
The following should do the job:
// ----------------------------- crc32b --------------------------------
/* This is the basic CRC-32 calculation with some optimization but no
table lookup. The the byte reversal is avoided by shifting the crc reg
right instead of left and by using a reversed 32-bit word to represent
the polynomial.
When compiled to Cyclops with GCC, this function executes in 8 + 72n
instructions, where n is the number of bytes in the input message. It
should be doable in 4 + 61n instructions.
If the inner loop is strung out (approx. 5*8 = 40 instructions),
it would take about 6 + 46n instructions. */
unsigned int crc32b(unsigned char *message) {
int i, j;
unsigned int byte, crc, mask;
i = 0;
crc = 0xFFFFFFFF;
while (message[i] != 0) {
byte = message[i]; // Get next byte.
crc = crc ^ byte;
for (j = 7; j >= 0; j--) { // Do eight times.
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
i = i + 1;
}
return ~crc;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I was asked an interview question: given a 6 byte input, which got from a big endian machine, please implement a function to convert/typecast it to 8 bytes, assume we do not know the endian of the machine running this function.
The point of the question seems to test my understanding of endianess because I was asked whether I know endianess before this question.
I do not know how to answer the question. e.g. do I need to pad 6 byte to 8 byte first? and how? Here is my code. is it correct?
bool isBigEndian(){
int num = 1;
char* b = (char*)(&num);
return b ? false:true;
}
long long* convert(char* arr[]){ //size is 6
long long* res = (long long*)malloc(long long);//...check res is NULL...
if (isBigEnian()){
for(int i = 0; i< 6; i++)
memset(res, i+2, arr[i]);
}
else {
for(int i = 0; i< 6; i++)
memset(res, i+2, arr[6-1-i]);
}
return res; //assume caller will free res.
}
update: to answer that my question is not clear, I just found a link: Convert Bytes to Int / uint in C with the similar question. based on my understanding of that, endianess of the host does matters. suppose if input is: char array[] = {01,02,03,04,05,06}, then if host is little endian, output is stored as 00,00,06,05,04,03,02,01, if big endian, output will be stored as 00,00,01,02,03,04,05,06, in both case, the 0000 are padded at beginning.
I am a kind of understand now: in the other machine, suppose there is a number xyz = 010203040506 because it is bigendian and 01 is MSB. so it is stored as char array = {01,02,03,04,05,06} where 01 has lowest address. then in this machine, if the machine is also big endian. it should be stored as {00,00,01,02,03,04,05,06 } where 01 is still MSB, so that it is cast to the same number int_64 xyz2 = 0000010203040506. but if the machine is little endian, it should be stored as {00,00,06,05,04,03,02,01 } where 01 is MSB has highest address in order for int_32 xyz2 = 0000010203040506.
please let me know if my undestanding is incorrect. and Can anybody tell me why 0000 is always padded at beginning no matter what endianess? shouldn't it be padded at the end if this machine is little endian since 00 is Most sign byte?
Before moving on, you should have asked for clarification.
What exactly means converting here? Padding each char with 0's? Prefixing each char with 0's?
I will assume that each char should be prefixed with 0's. This is a possible solution:
#include <stdint.h>
#include <limits.h>
#define DATA_WIDTH 6
uint64_t convert(unsigned char data[]) {
uint64_t res;
int i;
res = 0;
for (i = 0; i < DATA_WIDTH; i++) {
res = (res << CHAR_BIT) | data[i];
}
return res;
}
To append 0's to each char, we could, instead, use this inside the for:
res = (res << CHAR_BIT) | (data[i] << 2);
In an interview, you should always note the limitations for your solution. This solution assumes that the implementation provides uint64_t type (it is not required by the C standard).
The fact that the input is big endian is important because it lets you know that data[0] corresponds to the most significant byte, and it must remain so in your result. This solution works not matter what the target machine's endianness.
I don't understand why you think malloc is necessary. Why not just something like this?
long long convert(unsigned char data[]);
{
long long res;
res = 0;
for( int i=0;i < 6; ++i)
res = (res << 8) + data[i];
return res;
}