PIC32解除引用指针可能的编译器错误

时间:2014-07-02 14:45:01

标签: c pointers compiler-construction pic pic32

我正在使用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中的一个错误,还是有什么遗漏?

4 个答案:

答案 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。