word alignment on ARM? - c

How do I go about avoiding the compiler warning (warning: cast increases required alignment of target type) in the following code?
static int fill_color24 (VisVideo *video, VisColor *color)
{
int x, y;
uint32_t *buf;
uint8_t *rbuf = visual_video_get_pixels (video);
uint8_t *buf8;
int32_t cola =
(color->b << 24) |
(color->g << 16) |
(color->r << 8) |
(color->b);
int32_t colb =
(color->g << 24) |
(color->r << 16) |
(color->b << 8) |
(color->g);
int32_t colc =
(color->r << 24) |
(color->b << 16) |
(color->g << 8) |
(color->r);
for (y = 0; y < video->height; y++) {
buf = (uint32_t *) rbuf; // warning is for this line
for (x = video->width; x >= video->bpp; x -= video->bpp) {
*(buf++) = cola;
*(buf++) = colb;
*(buf++) = colc;
}
buf8 = (uint8_t *) buf;
*(buf8++) = color->b;
*(buf8++) = color->g;
*(buf8++) = color->r;
rbuf += video->pitch;
}
return VISUAL_OK;
}

I'm not sure you can. That function might return color array unaligned. You can't do anything to be able to read word from there.
You will have to read color by components (uint8_t) and then construct uint32_t from these by adding and shifting.

Related

Bitwise operations on 128-bit values on a non-sse2 arch

I am writing a routine in C, targeted for an embedded platform.In the routine I need to perform bitwise XOR and SHIFT RIGHT operations on 128-bit values. The target arch doesn't have SSE2, hence no native 128-bit operations supported. I came across this answer which simulates the SHIFT operations in software.
My question is, are there better ways of doing this, I mean with better data structure to represent 128-bit values and optimal way to simulate the SHIFT and XOR operations than using recursion(as done in the answer in the link). I wish to minimise usage of the limited stack memory.
You can use a structure to store 128 bit data as follows
typedef struct
{
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
} Type_128bit;
Then you can write a left shift function as follows
int leftshift(Type_128bit in, Type_128bit out, int value)
{
int val;
if (value >= 128)
{
return (-1); // error condition
}
else if (value < 32)
{
out->a = (in->a << value) | (in->b >> value);
out->b = (in->b << value) | (in->c >> value);
out->c = (in->c << value) | (in->d >> value);
out->d = in->d << value;
}
else if (value < 64)
{
val = value - 32;
out->a = (in->b << val) | (in->c >> val);
out->b = (in->c << val) | (in->d >> val);
out->c = (in->d << val);
out->d = 0x00;
}
else if (value < 96)
{
val = value - 64;
out->a = (in->c << val) | (in->d >> val);
out->b = (in->d << val);
out->c = 0x00;
out->d = 0x00;
}
else // value < 128
{
val = value - 96;
out->a = (in->d << val);
out->b = 0x00;
out->c = 0x00;
out->d = 0x00;
}
return (0); //success
}
This will avoid the recursion of the mentioned solution and give better runtime. But code size will increase and you need to carefully test the code.
uint32_t *shiftL(uint32_t *val, const size_t size, const size_t nbits) // <= 32
{
uint32_t mask = (1 << nbits) - 1;
mask <<= 32 - nbits;
for(size_t cword = size; cword - 1 ; cword --)
{
uint32_t temp = (val[cword - 2] & mask) >> nbits
val[cword - 1] <<= nbits;
val |= temp;
}
val[0] <<= nbits;
return val;
}

How to properly combine 4 bytes to make a float (single)

I have the following:
payload.data[i].data = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | (buf[11]);
note: payload.data[i].dataif of type float.
Using this: printf("test:%X%X%X%X", buf[8], buf[9], buf[10], buf[11]);, I have confirmed that the buffer contains #42C78A3D or DEC 99.77 (roughly).
This: printf("Float value:%f", payload.data[i].data prints out 1120373248.00, which is DEC for #42C78A00
It seems to me that for some reason, buf[11] is coming up empty.
Here is a more complete view of my code:
int i = 0;
int j = 0;
struct sensor_payload payload;
payload.key = (buf[0] << 8) | buf[1];
payload.id = (buf[2] << 8) | buf[3];
payload.type = (buf[4] << 8) | buf[5];
payload.fields = buf[6];
for(i = 0, j = 0; i < payload.fields; i++, j = j +33){
payload.data[i].data_type = buf[j+7];
payload.data[i].data = (buf[j+8] << 24) | (buf[j+9] << 16) | (buf[j+10] << 8) | (buf[j+11]);
slog(0, SLOG_DEBUG, "test:%X%X%X%X", buf[8], buf[9], buf[10], buf[11]);
}
payload.valid = true;
return payload;
and the definitions:
struct sensor_data{
uint8_t data_type;
float data;
};
struct sensor_payload{
uint16_t key, id, type;
uint8_t fields;
struct sensor_data data[4];
bool valid;
};
There's a lot in you code which is unclear. However, the only discrepancy I see is that you're putting index-offset entries into your data (notice the j+x pattern):
(buf[j+8] << 24) | (buf[j+9] << 16) | (buf[j+10] << 8) | (buf[j+11])
while printing non-offset entires:
slog(0, SLOG_DEBUG, "test:%X%X%X%X", buf[8], buf[9], buf[10], buf[11])
Technically, data you're printing and putting into the float is only the same for i==0.

Byte array to Decimal

i have a byte array (64-bit unsigned integer) :
byte array[8] = { 0x01,0xc9,0x98,0x57,0xd1,0x47,0xf3,0x60 }
i want to translate it into decimal..
when i'am using the calculator windows the result is :
128801567297500000
i don't find a way to do it in winapi or C ..
Any help is appreciated.
for a 4 bytes array i use the working code below
BYTE array[4] = { 0xC3,0x02,0x00,0x00 };
printf("Result : %d\n",(array[0]) | (array[1]) <<8 |(array[2]) <<16 | (array[3]) <<24 );
Result : 707
Cast the bytes to 64bit before the shifting. Currently they are implicitly promoted to int, which is a 32bit data type.
Assuming you use stdint:
uint64_t result = ((uint64_t)b[0]) | ((uint64_t)b[1] << 8) | ((uint64_t)b[2] << 16) | ((uint64_t)b[3] << 24) | ((uint64_t)b[4] << 32) | ((uint64_t)b[5] << 40) | ((uint64_t)b[6] << 48) | ((uint64_t)b[7] << 56);
or in reverse order (array is little endian; this will get the result you're seeing in windows calculator):
uint64_t result = ((uint64_t)b[7]) | ((uint64_t)b[6] << 8) | ((uint64_t)b[5] << 16) | ((uint64_t)b[4] << 24) | ((uint64_t)b[3] << 32) | ((uint64_t)b[2] << 40) | ((uint64_t)b[1] << 48) | ((uint64_t)b[0] << 56);
well, you can use
sprintf() to print the positional hex values to a string.
convert that string to decimal using strtoll() using base 16.
Sample code:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 128
int main()
{
char array[8] = { 0x01,0xc9,0x98,0x57,0xd1,0x47,0xf3,0x60 };
char arr[SIZE] = {0};
int i = 0;
unsigned long long res = 0;
for (i = 0; i < 8; i++)
sprintf((arr + (i * 2)), "%2x", (array[i] & 0xff));
printf("arr is %s\n", arr);
res = strtoll(arr, NULL, 16);
printf("res is %llu\n", res);
return 0;
}
int i;
byte array[8] = { 0x01,0xc9,0x98,0x57,0xd1,0x47,0xf3,0x60 };
unsigned long long v;
//Change of endian
for(i=0;i<4;++i){
byte temp = array[i];
array[i] = array[7-i];
array[7-i] = temp;
}
v = memcpy(&v, array, sizeof(v));//*(unsigned long long*)array;
printf("%llu ", v);

How to convert 64 bit int to binary presentation?

How to convert 64 bit int to binary presentation (big endian)? For reverse task I use these functions:
int readInt (struct str *buf) {
buf -> cur_len = buf -> cur_len + 4;
return
(((buf -> data[buf -> cur_len - 3 ] & 0xff) << 24) |
((buf -> data[buf -> cur_len - 2 ] & 0xff) << 16) |
((buf -> data[buf -> cur_len - 1 ] & 0xff) << 8) |
((buf -> data[buf -> cur_len ] & 0xff) << 0));
};
long unsigned int 32Bit(struct str *buf) { // 32
return ((long unsigned int)readInt(buf)) & 0xffffffffL;
};
long unsigned int 64Bit(struct str *buffer) { //64
long unsigned int result = 32Bit(buf);
result *= 4294967296.0;
return result;
}
Serialising a 64 bit unsigned number into an array of unsigned char, storing 8 bits in each in big-endian order, can be done like so:
void serialise_64bit(unsigned char dest[8], unsigned long long n)
{
dest[0] = (n >> 56) & 0xff;
dest[1] = (n >> 48) & 0xff;
dest[2] = (n >> 40) & 0xff;
dest[3] = (n >> 32) & 0xff;
dest[4] = (n >> 24) & 0xff;
dest[5] = (n >> 16) & 0xff;
dest[6] = (n >> 8) & 0xff;
dest[7] = (n >> 0) & 0xff;
}
You shouldn't use built-in types for serialization; instead, when you need to know the exact size of a type, you need fixed-width types:
#include <stdint.h>
unsigned char buf[8]; // 64-bit raw data
uint64_t little_endian_value =
(uint64_t)buf[0] + ((uint64_t)buf[1] << 8) + ((uint64_t)buf[2] << 16) + ... + ((uint64_t)buf[7] << 56);
uint64_t big_endian_value =
(uint64_t)buf[7] + ((uint64_t)buf[6] << 8) + ((uint64_t)buf[5] << 16) + ... + ((uint64_t)buf[0] << 56);
Similarly for 32-bit values, use uint32_t there. Make sure your source buffer uses unsigned chars.

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