Write and read an integer in a char * - c

I'm coding a little server in c (a chat server) and i want to write and read an integer (and other type of variable like short int, unsigned int blablabla) in my char *data.
I have a structure DataOutput :
typedef struct t_dataoutput
{
char *data;
unsigned int pos;
} DataOutput;
And i have a function to write an int :
int writeInt(DataOutput *out, int i)
{
// here i resize my char *data
out->data[out->pos] = (i >> 24);
out->data[out->pos + 1] = (i >> 16) & 0xff;
out->data[out->pos + 2] = (i >> 8) & 0xff;
out->data[out->pos + 3] = i & 0xff;
out->pos += 4;
}
In my main function i want to try my code :
int main()
{
DataOutput out;
out.writeInt(&out, 9000);
printf("%d\n", (out.data[0] << 24) | (out.data[1] << 16) | (out.data[2] << 8) | (out.data[3]));
}
But the result is not good ... Why ? I don't understand :(
Sorry for my english i'm french ^^ !
Thx for your help !

The DataOutput.data should be forced to unsigned char because char are sometimes signed, depending of the compiler, and shifting signed chars or casting them to int (even implicitly) will propagate the sign bit:
typedef struct t_dataoutput
{
unsigned char *data;
unsigned int pos;
} DataOutput;
The memory for out->data has to be allocated before filled.
You can use realloc in the writeInt function like that:
int writeInt(DataOutput *out, int i)
{
// here i resize my char *data
out->data = realloc(out->data, out->pos + 4);
// TODO: test if out->data == NULL --> not enough memory!
out->data[out->pos] = (i >> 24) & 0xff;
out->data[out->pos + 1] = (i >> 16) & 0xff;
out->data[out->pos + 2] = (i >> 8) & 0xff;
out->data[out->pos + 3] = i & 0xff;
out->pos += 4;
}

Of course I initialize my structure with this function :
void initDataOutput(DataOutput *out)
{
out->data = NULL;
out->pos = 0;
}
But i can't do that :
DataOutput out;
char tmp[4];
out.data = tmp;
out.pos = 0;
Because in my code i could write things like that for example :
DataOutput out;
writeInt(&out, 1);
writeString(&out, "Hello");
sendData(&out);
where the int is a kind of packet id and "Hello" is the connexion message, but if it's an other id it's not the same information in out->data
Oh sorry and I don't understand what you mean when you say : avoid shifting signed integers and chars
I must use an unsigned char *data in my DataOutput structure ?

Related

Swap alternate bytes in a integer

Problem: swap alternate bytes as below:
Input: uint8_t buf[4] = {0xab,0xcd,0xef,0xba};
Output: 0xcdababef
I have the below code for doing that but I am wondering if there is any better way to shorten the code.
#include <stdint.h>
#define SWAP_16(buf) (((buf & 0xFF00) >> 8) | ((buf & 0x00FF) << 8))
int main()
{
unsigned int value;
int i, j=0;
uint8_t buf[4] = {0,4,0,0};
unsigned int mask = 0xFFFF;
unsigned int tmp_value;
unsigned int size = 4;
for (i = size - 1 ;i >= 0; i--) {
tmp_value |= (buf[j] << 8*i);
j++;
}
value = SWAP_16((tmp_value & (mask << 16)) >> 16) << 16 |
SWAP_16(tmp_value & mask);
return 0;
}
Assuming unsigned int is 32-bits, you can simply use:
value = ((value & 0xff00ff00) >> 8) | ((value & 0x00ff00ff) << 8);
to swap the bytes in each pair of bytes in value. It's similar to your SWAP_16() macro except that it does both halves of the value at once.
unsigned int forward = 0x12345678;
unsigned int reverse;
unsigned char *f = &forward;
unsigned char *r = &reverse;
r[0]=f[3];
r[1]=f[2];
r[2]=f[1];
r[3]=f[0];
now reverse will be 0x78563412
Here is one way:
#include <stdio.h>
#include <stdint.h>
int main(void)
{
uint8_t buf[4] = {0xab,0xcd,0xef,0xba};
unsigned int out = buf[1] * 0x1000000u + buf[0] * 0x10000u + buf[3] * 0x100u + buf[2];
printf("%x\n", out);
}
It's not immediately clear from your question if it's not an option, but you could merely just swap the bytes in the array if you know the size won't change:
#include <stdio.h>
#include <stdint.h>
#define SWAPPED(b) { b[1], b[0], b[3], b[2] }
#define PRINT(b) printf("0x0%x\n", *((uint32_t*)b));
int main()
{
uint8_t buf[4] = {8,4,6,1};
uint8_t swapped[4] = SWAPPED(buf);
PRINT(buf);
PRINT(swapped);
return 0;
}
The output for this on my machine is:
0x01060408
0x06010804
This is because of endian-ness and printing an array casted to an integer type, but the bytes are swapped as you ask in your question.
Hope that helps.
Use a union
#include <stdint.h>
#define SWAP_VAR(T, v1, v2) do { \
T v = (v1); \
(v1) = (v2); \
(v2) = v; \
} while (0);
union U32
{
uint32_t u;
unsigned char a[4];
};
uint32_t swap32(uint32_t u)
{
union U32 u32 = {u};
SWAP_VAR(unsigned char, u32.a[0], u32.a[1]);
SWAP_VAR(unsigned char, u32.a[2], u32.a[3]);
return u32.u;
}
Use it like this:
#include <stdint.h>
uint32_t swap32(uint32_t u);
int main(void)
{
uint32_t u = 0x12345678;
u = swap32(u);
}
unsigned int n = ((unsigned int)buf[0] << 16) |
((unsigned int)buf[1] << 24) |
((unsigned int)buf[2] << 0) |
((unsigned int)buf[3] << 8);

ZIP 2.0 decryption produces unexpected results

I am trying to implement the 'Traditional PKWARE Decryption' described in Section 6.1 of the .ZIP File Format Specification (https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT), but the results are not as expected.
For testing, I am using a small text file zipped with TUGZip using no compression.
The CRC-32 of the original file is 0x7259B728.
The 12 byte 'encryption header' in the .ZIP file contains E6-8B-FE-EB-40-28-E1-55-4E-44-28-E0
The 'password' is 61-7A-62-79-63 (azbyc).
Encryption header after decryption contains C3-7D-EE-4C-11-B3-39-A3-97-55-21-B3
Section 6.1.6 of the specification says:
"After the header is decrypted, the last 1 or 2 bytes in Buffer should be the high-order word/byte of the CRC for the file being decrypted ...."
so I would expect 0x72, but I get 0xB3.
As far as I can tell, I followed the spec exactly, but I am still quite new to C so I recreated the program in C#, and got the same results. I'm obviously missing or misunderstanding something. Any help would be greatly appreciated.
Thank you in advance.
zip.c
//struct ZIP_INFO contains member 'uint32_t *keys'
//
//At initialisation, the values are:
//keys[0] = 0x12345678
//keys[1] = 0x23456789
//keys[2] = 0x34567890
unsigned char zip_decrypt_byte(uint32_t *keys)
{
uint16_t u = (uint16_t)((keys[2] & 0xFFFF) | 0x02);
return (unsigned char)(((u * (u ^ 0x01)) >> 8) & 0xFF);
}
void zip_decrypt_bytes(ZIP_INFO *info, unsigned char *buf, size_t len)
{
unsigned char *u = buf;
while (len--)
{
*u ^= zip_decrypt_byte(info->keys);
zip_update_keys(info->keys, u++);
}
}
void zip_set_password(ZIP_INFO *info, unsigned char *password, size_t len)
{
unsigned char *u = password;
while (len--)
zip_update_keys(info->keys, u++);
}
void zip_update_keys(uint32_t *keys, unsigned char *c)
{
unsigned char u;
keys[0] = crc_32(keys[0], c, 1);
keys[1] += (keys[0] & 0xFF);
keys[1] = ((keys[1] * 134775813) + 1);
u = (unsigned char)((keys[1] >> 24) & 0xFF);
keys[2] = crc_32(keys[2], &u, 1);
}
crc.c
static uint32_t crc_table[256];
uint32_t crc_32(uint32_t crc, unsigned char *buf, size_t len)
{
unsigned char *p;
crc ^= 0xFFFFFFFF;
p = buf;
while (len--)
crc = (crc_table[((crc ^ *p++) & 0xFF)] ^ (crc >> 8));
return (crc ^ 0xFFFFFFFF);
}
void crc_initialise()
{
uint32_t u0, u1, u2;
for (u0 = 0; u0 < 256; u0++)
{
u1 = u0;
for (u2 = 0; u2 < 8; u2++)
{
if (u1 & 0x01)
u1 = ((u1 >> 1) ^ 0xEDB88320);
else
u1 >>= 1;
}
crc_table[u0] = u1;
}
}
Contents of 'test.zip'
50-4B-03-04-14-00-01-00-00-00-F9-1E-55-47-28-B7-59-72-2B-00-00-00-1F-00-00-00-08-00-00-00-74-65-78-74-2E-74-78-74-E6-8B-FE-EB-40-28-E1-55-4E-44-28-E0-15-8E-13-49-CD-B0-B7-E4-43-40-9D-BA-5D-41-A8-BD-EA-47-07-AD-0E-4A-2F-BA-BD-1F-55-94-D3-6E-77-50-4B-01-02-14-00-14-00-01-00-00-00-F9-1E-55-47-28-B7-59-72-2B-00-00-00-1F-00-00-00-08-00-00-00-00-00-00-00-01-00-20-00-00-00-00-00-00-00-74-65-78-74-2E-74-78-74-50-4B-05-06-00-00-00-00-01-00-01-00-36-00-00-00-51-00-00-00-00-00

Reversing 7-bit integer encoding

When looking through code of a relatively big existing codebase, I found the following function:
int write_actual_size(unsigned int actual_size, int &out_size)
{
unsigned char second;
unsigned char third;
unsigned char fourth;
int result;
int usedBytes;
*(unsigned char *)out_size = actual_size | 0x80;
if ( actual_size < 0x80 ) {
*(unsigned char *)out_size = ((unsigned char)actual_size | 0x80) & 0x7F;
result = 1;
} else {
second = (actual_size >> 7) | 0x80;
*(unsigned char *)(out_size + 1) = second;
if (actual_size < 0x4000) {
*(unsigned char *)(out_size + 1) = second & 0x7F;
usedBytes = 2;
} else {
third = (actual_size >> 14) | 0x80;
*(unsigned char *)(out_size + 2) = third;
if (actual_size < 0x200000) {
*(unsigned char *)(out_size + 2) = third & 0x7F;
usedBytes = 3;
}
else {
fourth = (actual_size >> 21) | 0x80;
*(unsigned char *)(out_size + 3) = fourth;
if (actual_size < 0x10000000) {
*(unsigned char *)(out_size + 3) = fourth & 0x7F;
usedBytes = 4;
}
}
}
result = usedBytes;
}
return result;
}
This encodes a normal unsigned integer into one or more bytes, depending on the original input size.
As I understand, the left most bit is used to determine if there is a "follow-up" byte. I assume the reason for this is to save on bandwidth (even if it is just max 3 bytes per packet). Are these valid assumptions?
I want to make a read_actual_size version... Can I just linearly "shift right 7" every byte until I encounter a "0"?
Please don't be very harsh, I'm quite new to C.
A generic VLQ decoder would look something like this:
int decode_vlq(unsigned char *input)
{
int result = 0;
do
{
result = (result << 7) | (*input & 0x7F);
}
while (*input++ & 0x80);
return result;
}
I'm open to suggestions, since my C is pretty rusty, and I wrote this by hand.

Converting number to byte array

Hi I have a base 10 number for example 3198, and the hex representation is 0x0C7E
How do I convert that number to hex and put that hex value in a byte array in the format of [00][0C][7E], assuming the biggest hex value i can have is 0xffffff.
Maybe this will work ?
uint32_t x = 0x0C7E;
uint8_t bytes[3];
bytes[0] = (x >> 0) & 0xFF;
bytes[1] = (x >> 8) & 0xFF;
bytes[2] = (x >> 16) & 0xFF;
/* Go back. */
x = (bytes[2] << 16) | (bytes[1] << 8) | (bytes[0] << 0);
Number is already a continuous memory block - no need to convert it to yet ANOTHER array ! Just fetch separate bytes by using pointer arithmetic:
EDIT: Edited to be endianness-independent
#define FAST_ABS(x) ((x ^ (x>>31)) - (x>>31))
int is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
uint32_t num = 0xAABBCCDD;
uint32_t N = is_big_endian() * 3;
printf("first byte 0x%02X\n"
"second byte 0x%02X\n"
"third byte 0x%02X\n"
"fourth byte 0x%02X\n",
((unsigned char *) &num)[FAST_ABS(3 - N)],
((unsigned char *) &num)[FAST_ABS(2 - N)],
((unsigned char *) &num)[FAST_ABS(1 - N)],
((unsigned char *) &num)[FAST_ABS(0 - N)]
);
#include <stdio.h>
union uint32_value {
unsigned int value;
struct little_endian {
unsigned char fou;
unsigned char thi;
unsigned char sec;
unsigned char fir;
} le;
struct big_endian {
unsigned char fir;
unsigned char sec;
unsigned char thi;
unsigned char fou;
} be;
};
int main(void)
{
union uint32_value foo;
foo.value = 3198;
printf("%02x %02x %02x %02x\n", foo.le.fir, foo.le.sec, foo.le.thi, foo.le.fou);
return 0;
}

convert big endian to little endian in C [without using provided func] [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I need to write a function to convert big endian to little endian in C. I can not use any library function.
Assuming what you need is a simple byte swap, try something like
Unsigned 16 bit conversion:
swapped = (num>>8) | (num<<8);
Unsigned 32-bit conversion:
swapped = ((num>>24)&0xff) | // move byte 3 to byte 0
((num<<8)&0xff0000) | // move byte 1 to byte 2
((num>>8)&0xff00) | // move byte 2 to byte 1
((num<<24)&0xff000000); // byte 0 to byte 3
This swaps the byte orders from positions 1234 to 4321. If your input was 0xdeadbeef, a 32-bit endian swap might have output of 0xefbeadde.
The code above should be cleaned up with macros or at least constants instead of magic numbers, but hopefully it helps as is
EDIT: as another answer pointed out, there are platform, OS, and instruction set specific alternatives which can be MUCH faster than the above. In the Linux kernel there are macros (cpu_to_be32 for example) which handle endianness pretty nicely. But these alternatives are specific to their environments. In practice endianness is best dealt with using a blend of available approaches
By including:
#include <byteswap.h>
you can get an optimized version of machine-dependent byte-swapping functions.
Then, you can easily use the following functions:
__bswap_32 (uint32_t input)
or
__bswap_16 (uint16_t input)
#include <stdint.h>
//! Byte swap unsigned short
uint16_t swap_uint16( uint16_t val )
{
return (val << 8) | (val >> 8 );
}
//! Byte swap short
int16_t swap_int16( int16_t val )
{
return (val << 8) | ((val >> 8) & 0xFF);
}
//! Byte swap unsigned int
uint32_t swap_uint32( uint32_t val )
{
val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF );
return (val << 16) | (val >> 16);
}
//! Byte swap int
int32_t swap_int32( int32_t val )
{
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF );
return (val << 16) | ((val >> 16) & 0xFFFF);
}
Update : Added 64bit byte swapping
int64_t swap_int64( int64_t val )
{
val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL );
val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL );
return (val << 32) | ((val >> 32) & 0xFFFFFFFFULL);
}
uint64_t swap_uint64( uint64_t val )
{
val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL );
val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL );
return (val << 32) | (val >> 32);
}
Here's a fairly generic version; I haven't compiled it, so there are probably typos, but you should get the idea,
void SwapBytes(void *pv, size_t n)
{
assert(n > 0);
char *p = pv;
size_t lo, hi;
for(lo=0, hi=n-1; hi>lo; lo++, hi--)
{
char tmp=p[lo];
p[lo] = p[hi];
p[hi] = tmp;
}
}
#define SWAP(x) SwapBytes(&x, sizeof(x));
NB: This is not optimised for speed or space. It is intended to be clear (easy to debug) and portable.
Update 2018-04-04
Added the assert() to trap the invalid case of n == 0, as spotted by commenter #chux.
If you need macros (e.g. embedded system):
#define SWAP_UINT16(x) (((x) >> 8) | ((x) << 8))
#define SWAP_UINT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | ((x) << 24))
Edit: These are library functions. Following them is the manual way to do it.
I am absolutely stunned by the number of people unaware of __byteswap_ushort, __byteswap_ulong, and __byteswap_uint64. Sure they are Visual C++ specific, but they compile down to some delicious code on x86/IA-64 architectures. :)
Here's an explicit usage of the bswap instruction, pulled from this page. Note that the intrinsic form above will always be faster than this, I only added it to give an answer without a library routine.
uint32 cq_ntohl(uint32 a) {
__asm{
mov eax, a;
bswap eax;
}
}
As a joke:
#include <stdio.h>
int main (int argc, char *argv[])
{
size_t sizeofInt = sizeof (int);
int i;
union
{
int x;
char c[sizeof (int)];
} original, swapped;
original.x = 0x12345678;
for (i = 0; i < sizeofInt; i++)
swapped.c[sizeofInt - i - 1] = original.c[i];
fprintf (stderr, "%x\n", swapped.x);
return 0;
}
here's a way using the SSSE3 instruction pshufb using its Intel intrinsic, assuming you have a multiple of 4 ints:
unsigned int *bswap(unsigned int *destination, unsigned int *source, int length) {
int i;
__m128i mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
for (i = 0; i < length; i += 4) {
_mm_storeu_si128((__m128i *)&destination[i],
_mm_shuffle_epi8(_mm_loadu_si128((__m128i *)&source[i]), mask));
}
return destination;
}
Will this work / be faster?
uint32_t swapped, result;
((byte*)&swapped)[0] = ((byte*)&result)[3];
((byte*)&swapped)[1] = ((byte*)&result)[2];
((byte*)&swapped)[2] = ((byte*)&result)[1];
((byte*)&swapped)[3] = ((byte*)&result)[0];
This code snippet can convert 32bit little Endian number to Big Endian number.
#include <stdio.h>
main(){
unsigned int i = 0xfafbfcfd;
unsigned int j;
j= ((i&0xff000000)>>24)| ((i&0xff0000)>>8) | ((i&0xff00)<<8) | ((i&0xff)<<24);
printf("unsigned int j = %x\n ", j);
}
Here's a function I have been using - tested and works on any basic data type:
// SwapBytes.h
//
// Function to perform in-place endian conversion of basic types
//
// Usage:
//
// double d;
// SwapBytes(&d, sizeof(d));
//
inline void SwapBytes(void *source, int size)
{
typedef unsigned char TwoBytes[2];
typedef unsigned char FourBytes[4];
typedef unsigned char EightBytes[8];
unsigned char temp;
if(size == 2)
{
TwoBytes *src = (TwoBytes *)source;
temp = (*src)[0];
(*src)[0] = (*src)[1];
(*src)[1] = temp;
return;
}
if(size == 4)
{
FourBytes *src = (FourBytes *)source;
temp = (*src)[0];
(*src)[0] = (*src)[3];
(*src)[3] = temp;
temp = (*src)[1];
(*src)[1] = (*src)[2];
(*src)[2] = temp;
return;
}
if(size == 8)
{
EightBytes *src = (EightBytes *)source;
temp = (*src)[0];
(*src)[0] = (*src)[7];
(*src)[7] = temp;
temp = (*src)[1];
(*src)[1] = (*src)[6];
(*src)[6] = temp;
temp = (*src)[2];
(*src)[2] = (*src)[5];
(*src)[5] = temp;
temp = (*src)[3];
(*src)[3] = (*src)[4];
(*src)[4] = temp;
return;
}
}
EDIT: This function only swaps the endianness of aligned 16 bit words. A function often necessary for UTF-16/UCS-2 encodings.
EDIT END.
If you want to change the endianess of a memory block you can use my blazingly fast approach.
Your memory array should have a size that is a multiple of 8.
#include <stddef.h>
#include <limits.h>
#include <stdint.h>
void ChangeMemEndianness(uint64_t *mem, size_t size)
{
uint64_t m1 = 0xFF00FF00FF00FF00ULL, m2 = m1 >> CHAR_BIT;
size = (size + (sizeof (uint64_t) - 1)) / sizeof (uint64_t);
for(; size; size--, mem++)
*mem = ((*mem & m1) >> CHAR_BIT) | ((*mem & m2) << CHAR_BIT);
}
This kind of function is useful for changing the endianess of Unicode UCS-2/UTF-16 files.
If you are running on a x86 or x86_64 processor, the big endian is native. so
for 16 bit values
unsigned short wBigE = value;
unsigned short wLittleE = ((wBigE & 0xFF) << 8) | (wBigE >> 8);
for 32 bit values
unsigned int iBigE = value;
unsigned int iLittleE = ((iBigE & 0xFF) << 24)
| ((iBigE & 0xFF00) << 8)
| ((iBigE >> 8) & 0xFF00)
| (iBigE >> 24);
This isn't the most efficient solution unless the compiler recognises that this is byte level manipulation and generates byte swapping code. But it doesn't depend on any memory layout tricks and can be turned into a macro pretty easily.

Resources