Reputation: 141
I have a buffer where each entry in the buffer is 8 bits in size:
uint8_t Buffer[10] = {0x12,0x34,0x56,0x78,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6};
What I need to do is to create pointers to that array, for example 16 bit and 32 bit pointers. For example:
uint32_t *x;
x = Buffer;
uint32_t *y;
y = Buffer+4;
uint16_t *z;
z = Buffer+8;
Where each variable would then read from the array, for example:
x = 0x78563412
y = 0xf4f3f2f1
z = 0xf6f5
This works completely fine, the problem is that I'm getting warnings about incompatible pointer types. So I was wondering if there is an alternative way of doing this or if I'll just have to live with the warnings? Or am I simply doing this completely the wrong way?
Please note that this code will be executed on a single type of platform where the endianness is always the same and the size of data types is always the same.
Upvotes: 4
Views: 10462
Reputation: 38218
You should heed the warnings; what you're doing is undefined behavior. Type aliasing like that is undefined behavior, particularly since there is no guarantee that Buffer
has the correct alignment such that it can be accessed as an int
/short
. If Buffer
has the correct alignment, then you can just explicitly cast and it's okay (and the warning will go away).
You have two options:
One, you align the buffer as the larger of the two types. Be careful that your pointer arithmetic doesn't throw off the alignment:
#include <stdalign.h>
alignas(int) unsigned char Buffer[10] = {0x12,0x34,0x56,0x78,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6};
unsigned int *x;
x = (unsigned int*)(Buffer);
unsigned int *y;
y = (unsigned int*)(Buffer+4);
unsigned short *z;
z = (unsigned short*)(Buffer+8);
Two, you create an unsigned int
/unsigned short
variable and then memcpy
the bytes you're interested in into the variable:
unsigned int x;
memcpy(&x, Buffer, 4);
unsigned int y;
memcpy(&y, Buffer + 4, 4);
unsigned short z;
memcpy(&z, Buffer + 8, 2);
Upvotes: 7
Reputation: 1145
You might want to use a union
#include <stdint.h>
#include <stdio.h>
typedef union{
uint8_t Buffer[10];
struct{
uint32_t x;
uint32_t y;
uint16_t z;
};
}MYSTRUCT;
int main(){
MYSTRUCT b = {0x12,0x34,0x56,0x78,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6};
printf("x=%#x y=%#x z=%#x\n",b.x,b.y,b.z);
return 0;
}
Upvotes: 2
Reputation: 726559
The problem with your approach is that it assumes a particular endianness of underlying hardware. Different computers will interpret a sequence of hex bytes
01 23 45 67
as eiter
01234567 or 67452301
Your program may compile and run on both systems, but since the result is hardware-specific, the compiler must warn you of the possibility.
The proper way of forcing a particular endianness is by using an array of integers, convert them using hton and ntoh functions, and set individual bytes either directly by casting a pointer to unsigned char*, or with memcpy.
Upvotes: 2