我有一个缓冲区,缓冲区中的每个条目大小为8位:
uint8_t Buffer[10] = {0x12,0x34,0x56,0x78,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6};
我需要做的是创建指向该数组的指针,例如16位和32位指针。例如:
uint32_t *x;
x = Buffer;
uint32_t *y;
y = Buffer+4;
uint16_t *z;
z = Buffer+8;
然后,每个变量将从数组中读取,例如:
x = 0x78563412
y = 0xf4f3f2f1
z = 0xf6f5
这完全正常,问题是我收到有关不兼容指针类型的警告。所以我想知道是否有另一种方法可以做到这一点,或者我是否只需要接受警告?或者我只是完全以错误的方式做这件事?
请注意,此代码将在单一类型的平台上执行,其中字节顺序始终相同且数据类型的大小始终相同。
答案 0 :(得分:6)
你应该留意警告;你正在做的是未定义的行为。像这样的类型别名是未定义的行为,特别是因为无法保证Buffer
具有正确的对齐方式,因此可以将其作为int
/ short
进行访问。如果Buffer
具有正确的对齐方式,那么您可以明确地投射并且它没问题(并且警告将消失)。
您有两种选择:
首先,将缓冲区对齐为两种类型中较大的一种。请注意,指针算术不会抛弃对齐:
#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);
两,你创建一个unsigned int
/ unsigned short
变量,然后memcpy
你感兴趣的字节到变量中:
unsigned int x;
memcpy(&x, Buffer, 4);
unsigned int y;
memcpy(&y, Buffer + 4, 4);
unsigned short z;
memcpy(&z, Buffer + 8, 2);
答案 1 :(得分:2)
您的方法的问题在于它假定底层硬件的特定字节序。不同的计算机将解释十六进制字节序列
01 23 45 67
as eiter
01234567 or 67452301
您的程序可以在两个系统上编译和运行,但由于结果是特定于硬件的,编译器必须警告您这种可能性。
强制使用特定字节序的正确方法是使用整数数组,使用hton和ntoh函数转换它们,并通过将指针转换为unsigned char *或使用memcpy直接设置单个字节。
答案 2 :(得分:2)
您可能想要使用联合
#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;
}