我正在使用XC32编译器处理PIC32MX795F512L的一些代码。我需要从作为void *传递给函数的缓冲区中读取数据。我需要将数据作为无符号32位整数数组读取。问题是当我将void *转换为uint32 *并尝试读取该数组的索引0处的值时,处理器会调用一般错误处理程序,而如果我将void *转换为uint8 *并执行某些操作位操作得到相同的数据,它可以正常工作。
代码如下所示:
void foo(void* data, uint32 length)
{
uint32 i,j;
uint32 block;
for(i = 0, j = 0; i < length; i+= sizeof(uint32),j++)
{
printfUART(DEBUG_UART,"Debug 0\r\n");
#if 0//working code
block = ((uint8*)data)[i + 3];
block <<= 8;
block |= ((uint8*)data)[i + 2];
block <<= 8;
block |= ((uint8*)data)[i + 1];
block <<= 8;
block |= ((uint8*)data)[i + 0];
#else//not working code
block = ((uint32*)data)[j];
#endif
printfUART(DEBUG_UART,"Debug 1\r\n");
}
}
如果您将#if 0
更改为#if 1
代码按预期工作,我会在循环中多次打印"Debug 0"
和"Debug 1"
。
但如果按原样保留,“Debug 0”只打印一次,然后代码跳出循环进入编译器设置的cpu通用错误处理程序。这是XC32 ompiler中的一个错误,还是有什么遗漏?
答案 0 :(得分:5)
我认为这是一个对齐问题。
如果data
不在偶数地址(例如因为它实际上是一个字节数组),那么在您的平台上无法以32位方式访问它。
C标准(ISO / IEC 9899:1999,6.3.2.3)说:
指向对象或不完整类型的指针可能会转换为指向其他对象的指针 对象或不完整的类型。如果生成的指针未正确对齐 指向类型,行为未定义。
答案 1 :(得分:2)
而不是可能存在对齐问题的block = ((uint32*)data)[j];
,您可以通过以下方式实现预期的效果:
memcpy( &block, data + j, sizeof block );
请注意,这在概念上与从单个字节构建的版本不同。这取决于你的CPU如何表示整数(通常称为&#34; endianness&#34;)。
答案 2 :(得分:0)
下面是您的代码,添加了调试输出。在主循环中,它在它占用的内存上运行了一些数组(故意)并且它到目前为止工作正常(尽管它可能仍然是平台不兼容)。我很确定你的foo()
是好的,编译器也是如此,但你可能错误地称它为。使用调试输出检查所有地址和值并检查范围。
void foo(void* data, unsigned int length)
{
unsigned int i,j;
unsigned int block;
for(i = 0, j = 0; i < length; i+= sizeof(unsigned int ),j++)
{
printf("Debug 0\r\n");
printf("i: 0x%d\r\n", i);
printf("j: 0x%d\r\n", j );
#if 0//working code
block = ((unsigned char*)data)[i + 3];
block <<= 8;
block |= ((unsigned char*)data)[i + 2];
block <<= 8;
block |= ((unsigned char*)data)[i + 1];
block <<= 8;
block |= ((unsigned char*)data)[i + 0];
#else//not working code
block = ((unsigned int *)data)[j];
#endif
printf("data: 0x%x\r\n", data );
printf( " ((unsigned int )data +j) = 0x%x\r\n", ((unsigned int )data +j) );
printf( " ((unsigned int *)data)[j] = 0x%x\r\n", ((unsigned int *)data)[j]);
printf("block: 0x%x\r\n", block );
printf("Debug 1\r\n");
printf("\r\n");
printf("\r\n");
}
}
int main(void)
{
unsigned int array[10] = {0xFE,0xED,0xBA,0xBE,0xDE,0xAD,0xBE,0xEF,0xCA,0xFE};
printf ("array: 0x%x\r\n",array);
printf ("array[1]:%x\r\n",array[1]);
foo((void*) array, 50);
}
其输出:
数组:0x1d0fdde0数组[1]:ed调试0 i:0x0 j:0x0数据:0x1d0fdde0 ((unsigned int)data + j)= 0x1d0fdde0((unsigned int *)data)[j] = 0xfe块:0xfe调试1
调试0 i:0x4 j:0x1数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fdde1((unsigned int *)data)[j] = 0xed block:0xed Debug 1
调试0 i:0x8 j:0x2数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fdde2((unsigned int *)data)[j] = 0xba block:0xba Debug 1
调试0 i:0x12 j:0x3数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fdde3((unsigned int *)data)[j] = 0xbe block:0xbe Debug 1
调试0 i:0x16 j:0x4数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fdde4((unsigned int *)data)[j] = 0xde block:0xde Debug 1
调试0 i:0x20 j:0x5数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fdde5((unsigned int *)data)[j] = 0xad block:0xad Debug 1
调试0 i:0x24 j:0x6数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fdde6((unsigned int *)data)[j] = 0xbe block:0xbe Debug 1
调试0 i:0x28 j:0x7数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fdde7((unsigned int *)data)[j] = 0xef block:0xef Debug 1
调试0 i:0x32 j:0x8数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fdde8((unsigned int *)data)[j] = 0xca block:0xca Debug 1
调试0 i:0x36 j:0x9数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fdde9((unsigned int *)data)[j] = 0xfe block:0xfe Debug 1
调试0 i:0x40 j:0x10数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fddea((unsigned int *)data)[j] = 0x0 block:0x0 Debug 1
调试0 i:0x44 j:0x11数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fddeb((unsigned int *)data)[j] = 0x0 block:0x0 Debug 1
调试0 i:0x48 j:0x12数据:0x1d0fdde0((unsigned int)data + j)= 0x1d0fddec((unsigned int *)data)[j] = 0x0 block:0x0 Debug 1
如果您使用更多详细信息和/或新结果进行更新,任何人都可以获得更多的理解,更好地做出答案,您将获得更加可靠的答案。
答案 3 :(得分:0)
undur_gongor是正确的,这是一个对齐问题。请考虑以下结构:
struct demo {
uint8_t char_var;
uint16_t short_var;
uint32_t int_var;
};
如果打包结构放置在对齐的地址0处,那么您有一个16位变量,从奇数地址1开始,32位变量从地址3开始.PIC32只能读取偶数地址的16位变量(0 ,2,4 ...)和来自类似对齐的地址(0,4,8)的32位变量。
访问压缩结构或类似结构时,编译器会采取额外步骤。解决方案通常是写入不受对齐影响的单个字节。正如M.M所提到的,最简单的解决方案是使用memcpy。