PIC32解引用指针可能存在编译器错误

PIC32解引用指针可能存在编译器错误,c,pointers,compiler-construction,pic,pic32,C,Pointers,Compiler Construction,Pic,Pic32,我正在使用XC32编译器为PIC32MX795F512L编写一些代码。我需要从作为void*传递给函数的缓冲区中读取数据。我需要以无符号32位整数数组的形式读取数据。问题是,当我将void*强制转换为uint32*并尝试读取该数组的索引0处的值时,处理器会调用常规错误处理程序,而如果我将void*强制转换为uint8*并执行一些位操作以获取相同的数据,则它会正常工作 代码如下所示: void foo(void* data, uint32 length) { uint32 i,j;

我正在使用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");
    }
}
void foo(void*数据,uint32长度)
{
uint32 i,j;
uint32区块;
对于(i=0,j=0;iblock我认为这是一个对齐问题

如果
数据
不在偶数地址(例如,因为它实际上是一个字节数组),则在您的平台上无法以32位方式访问它

C标准(ISO/IEC 9899:1999,6.3.2.3)规定:

指向对象或不完整类型的指针可能会转换为指向其他类型的指针 对象或不完整的类型。如果结果指针未正确对齐 指向类型时,行为未定义


下面是添加了调试输出的代码。在主循环中,它在占用的内存上运行(故意)有点超出数组,到目前为止运行良好(但可能仍然与平台不兼容)。我非常确定您的
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);

}
void foo(void*数据,无符号整数长度)
{
无符号整数i,j;
无符号整型块;
对于(i=0,j=0;iblock=((uint32*)数据)[j];
可能存在对齐问题,您可以通过以下方式实现预期效果:

memcpy( &block, data + j, sizeof block );

注意,这在概念上不同于从单个字节建立的版本。这取决于CPU如何表示整数(通常称为“Enthness”)。

UnurugGangor是正确的,这是一个对齐问题。请考虑下面的结构:

struct demo {
   uint8_t char_var;
   uint16_t short_var;
   uint32_t int_var;
};
如果将压缩结构置于对齐地址0处,则16位变量从奇数地址1开始,32位变量从地址3开始。PIC32只能从偶数地址(0、2、4…)读取16位变量,从类似对齐地址(0、4、8)读取32位变量


当访问压缩结构或类似结构时,编译器会采取额外的步骤。解决方案通常是写入不受对齐影响的单个字节。正如M.M提到的,最简单的解决方案是使用memcpy。

抱歉,这是一个复制粘贴错误没有问题。我也认为这是一个对齐问题。请尝试打印d的原始地址ata.我打赌这不是一个均匀的地址。正如RuslanGerasimov所指出的(我想),如果
length
不是4的倍数,则您读取的数据超出了输入缓冲区。您应该编写代码以确保不会发生这种情况,例如,在开始循环之前,将
length
四舍五入到最接近的4倍数。@Matt McNabb这通常是正确的,但对于这个特定函数,传入的大小是一个常数,即它是4的倍数,不管怎样,它只是调试代码,所以我不担心它。这不是违反了c标准吗?我的意思是,我写的不是有效的c吗?不,它不是。你通常不能自由转换指针。唯一的保证是,你可以通过指向字符的指针(“字节方式”)访问所有对象.@S E检查您的编译器手册,它们可能是预处理器宏,您可以使用它们来强制对齐某些变量。@BrandonYates在PIC32上通常没有任何操作系统。我认为C运行时在无效指针取消引用时会失败。@BrandonYates取消引用NULL也不是有效的C。只是因为有些东西没有给出mpilation错误并不意味着它是有效的。当有人对答案投了否决票时,最好留下一条评论,说明出现错误的地方。否决票的可能原因:在以前没有缓冲区溢出的地方引入了缓冲区溢出(???),您将
无符号整数
转换为
无符号整数
,但没有解决问题的实际原因(对齐问题);您说您“非常确定”仅仅因为您的版本似乎有效就可以了,但这一结论是不合理的。@MichaelDorgan谢谢各位,我修正了我的答案。您是在pic32微控制器上运行此代码吗?而且您传入的数据是以32位整数数组对齐的,因此此示例未显示无效对齐是否会导致问题。