C语言指针运算:
C语言指针运算:
指针运算的关键是:以指针所指对象的数据类型为最小运算单位。
例如:整型占四个字节,如果一个指向整型的指针自增1,那么该指针的新的指向是当前指向后移动四个字节。这就是指针的运算,很简单吧,其实运算的关键是数据类型。OK,然后再说明两个注意事项:
(1)数组指针是不能自增的:
int a[3]={1,2,3};
a++;//这一句是不对的,数组指针不能自增
(2)(void*)的妙用:
(void*)常常用来打破指针运算必须以数据类型为最小单位的这一定律:
int a={1,2,3};
unsigned char *p=(void*)a;
int是四个字节,unsigned char 是1个字节,经过以上两句,p指向了a的首地址,但是p自增1,并不会移动四个字节,而是移动1个字节。也就是说,虽然p指向了int数据类型的地址,但是p指针的运算并不遵从int型指针每次移动四个字节,p本质上还是unsigned char指针。
到这里,大家应该就明白(void*)的原理了吧,其实就是让不同类型的指针指向同一个地址,然后指针的运算性质也发生了改变。这具体有什么用呢?举个应用的例子吧:
比如我们通过STM32往W25Q64_flash中存储数据,用的SPI协议每次传输一个字节,可是小数有多个字节啊,如何传输小数呢?比如说传输double类型的数据,可以这样做:
double buffer = 123.456;
unsigned char * p=(void*)&buffer;//然单字节运算的指针p指向buffer的地址
//sendByte函数:给定一个字节数据的指针,每次传输该指针指向的字节
while(sizeof(&buffer)--)
{
sendByte(p)//指针p每次移动一个字节,一共移动8个字节(因为sizeof(&buffer)等于8)
p++;
}
这样就可以成功通过SPI协议每次向flash存储一个小数,当然实际的程序还要写相应存储数据的命令,并且可能是传整个数组的数据,要比这个程序复杂的多,这里只是把存储小数的核心部分展示出来。
参考野火的历程,完整的函数是这样的:
/**
* @brief 对FLASH按页写入数据,调用本函数写入数据前需要先擦除扇区,一次最多可以写入256个字节
* @param pBuffer,要写入数据的指针
* @param WriteAddr,写入地址
* @param NumByteToWrite,写入数据长度,必须小于等于SPI_FLASH_PerWritePageSize
* @retval 无
*/
void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
/* 发送FLASH写使能命令 */
SPI_FLASH_WriteEnable();
/* 选择FLASH: CS低电平 */
SPI_FLASH_CS_LOW();
/* 写页写指令*/
SPI_FLASH_SendByte(W25X_PageProgram);
/*发送写地址的高位*/
SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
/*发送写地址的中位*/
SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
/*发送写地址的低位*/
SPI_FLASH_SendByte(WriteAddr & 0xFF);
if(NumByteToWrite > SPI_FLASH_PerWritePageSize)
{
NumByteToWrite = SPI_FLASH_PerWritePageSize;
FLASH_ERROR("SPI_FLASH_PageWrite too large!");
}
/* 写入数据*/
while (NumByteToWrite--)
{
/* 发送当前要写入的字节数据 */
SPI_FLASH_SendByte(*pBuffer);
/* 指向下一字节数据 */
pBuffer++;
}
/* 停止信号 FLASH: CS 高电平 */
SPI_FLASH_CS_HIGH();
/* 等待写入完毕*/
SPI_FLASH_WaitForWriteEnd();
}
使用此函数写入小数,给函数实参的时候,就要用(void*)来修饰传入的指针.
以上就是关于指针的一些个人见解,哎,我很努力地想把自己的想法表达清楚,但是奈何表达能力有限,哎,不说了。大家再见