这与这个问题息息相关。
我正在使用libusb
. 查看库的源代码,我看到他们正在使用指针来解析数据和填充structs
。
例子:
来自libusb.h
:
struct libusb_endpoint_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
uint8_t bRefresh;
uint8_t bSynchAddress;
const unsigned char *extra;
int extra_length;
};
来自descriptor.c
:
struct libusb_endpoint_descriptor *endpoint
unsigned char *buffer
int host_endian
usbi_parse_descriptor(buffer, "bbbbwbbb", endpoint, host_endian);
哪里usbi_parse_descriptor
是:
int usbi_parse_descriptor(
unsigned char *source,
const char *descriptor,
void *dest,
int host_endian)
{
unsigned char *sp = source;
unsigned char *dp = dest;
uint16_t w;
const char *cp;
for (cp = descriptor; *cp; cp++) {
switch (*cp) {
case 'b': /* 8-bit byte */
*dp++ = *sp++;
break;
case 'w': /* 16-bit word, convert from little endian to CPU */
dp += ((uintptr_t)dp & 1); /* Align to word boundary */
if (host_endian) {
memcpy(dp, sp, 2);
} else {
w = (sp[1] << 8) | sp[0];
*((uint16_t *)dp) = w;
}
sp += 2;
dp += 2;
break;
}
}
return (int) (sp - source);
}
我的问题是使用char
指针来遍历缓冲区。
一个风险难道不能被编译器
uint8_t
对齐为一个整数,例如,一个整数——从而导致错误的地址吗?错误地址是指 struct 中变量的地址,它指向:uint32_t
*dp++
libusb_endpoint_descriptor
dp
unsigned char *buffer = REPLY from request to USB device. struct libusb_endpoint_descriptor *endpoint; unsigned char *dp = (void*) endpoint; *dp = buffer[0] ==> struct libusb_endpoint_descriptor -> bLength *++dp = buffer[1] ==> struct libusb_endpoint_descriptor -> bDescriptorType ... v ^ | | +--- does this guaranteed align with this ----------------+
这会发生什么?:
dp += ((uintptr_t)dp & 1); /* Align to word boundary */
如果结构在内存中是这样的:
ADDRESS TYPE NAME
0x000a0 uint8_t var1
0x000a1 uint16_t var2
0x000a3 uint8_t var3
并dp
指向var1
; 0x000a0
,上面的语句会做什么?