编程的时候,看到下面的一个函数:
eMBErrorCode
eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
{
eMBErrorCode eStatus = MB_ENOERR;
ENTER_CRITICAL_SECTION( );
assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );
/* Length and CRC check */
if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
&& ( prvucMBLRC( ( UCHAR * ) ucASCIIBuf, usRcvBufferPos ) == 0 ) )
{
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*pucRcvAddress = ucASCIIBuf[MB_SER_PDU_ADDR_OFF];
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
* size of address field and CRC checksum.
*/
*pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC );
/* Return the start of the Modbus PDU to the caller. */
*pucFrame = ( UCHAR * ) & ucASCIIBuf[MB_SER_PDU_PDU_OFF];
}
else
{
eStatus = MB_EIO;
}
EXIT_CRITICAL_SECTION( );
return eStatus;
}
当看到UCHAR ** pucFrame的时候就优点晕了。不就是传出一个地址吗?干吗还要用指向指针的指针?于是,顺手修改了程序,将那个形参变成了UCHAR * pucFrame,具体的函数也变成了下面的样子:
eMBErrorCode
eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR * pucFrame, USHORT * pusLength )
{
eMBErrorCode eStatus = MB_ENOERR;
ENTER_CRITICAL_SECTION( );
assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );
/* Length and CRC check */
if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
&& ( prvucMBLRC( ( UCHAR * ) ucASCIIBuf, usRcvBufferPos ) == 0 ) )
{
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*pucRcvAddress = ucASCIIBuf[MB_SER_PDU_ADDR_OFF];
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
* size of address field and CRC checksum.
*/
*pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC );
/* Return the start of the Modbus PDU to the caller. */
pucFrame = ( UCHAR * ) & ucASCIIBuf[MB_SER_PDU_PDU_OFF];
}
else
{
eStatus = MB_EIO;
}
EXIT_CRITICAL_SECTION( );
return eStatus;
}
编译后运行,却得不到自己想要的结果。只得回来再分析这个函数。首先搜索到CSDN上的一篇文章;http://dev.csdn.net/author/kgdiwss/477390ddb16b44faa06b6c7014908469.html,里面又好好地对指针做了分析。我下面就把自己的理解再写一遍,以加深印象。
1,指针在编译的时候会变成什么?
如果我们如下声明变量:
char a;
shourt int i;
short int *pi;
那么编译的时候,编译器会在内存空间的某处为上面的变量开辟存储空间,下面是一个可能的示意图:
内存地址 1 2 3 4 5 6 7 8 9 10
------------------------------
|int a |short int i |short int *pi |
如上所示,int a 占用一个字节,short int i 占用2个字节, short int *pi 占用2个字节。当我们做了如下的赋值的时候:
i = 88;
pi = &a;
内存映象会得到改变:
|int a | 88 | 2 |
从上面可以看到,pi是个指针,他的值是2,是变量 i 的内存的起始地址。当我们对 *pi 进行操作的时候,其实就是对变量i 进行操作。如 *pi = 66; ,则等价 i = 66;。下面我们再分析指向指针的指针。指针变量本身跟其他变量一样也是在某个内存地址中存储的,我们也可以让一个指针指向这个地址(指针)。看如下代码:
short int **ppi;
ppi = π
首先声明了一个指向指针的指针变量ppi,这个ppi是用来存储一个short int *类型指针变量的地址的。第二句的意思是pi的地址赋值给ppi,就是将地址值4给ppi,如下图表示:
|int a | short int i |short int *pi|short int **ppi |
|int a | 88 | 2 | 4 |
这样,ppi的值为4,就是pi在内存中的起始地址
*ppi的值为2,是pi的值
**ppi的值是88,是i的值,也是*pi的值
有了上面的分析,我们在看上面那个错误的函数:
eMBErrorCode
eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR * pucFrame, USHORT * pusLength )
{
eMBErrorCode eStatus = MB_ENOERR;
ENTER_CRITICAL_SECTION( );
assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );
/* Length and CRC check */
if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
&& ( prvucMBLRC( ( UCHAR * ) ucASCIIBuf, usRcvBufferPos ) == 0 ) )
{
/* Save the address field. All frames are passed to the upper layed
* and the decision if a frame is used is done there.
*/
*pucRcvAddress = ucASCIIBuf[MB_SER_PDU_ADDR_OFF];
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
* size of address field and CRC checksum.
*/
*pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC );
/* Return the start of the Modbus PDU to the caller. */
pucFrame = ( UCHAR * ) & ucASCIIBuf[MB_SER_PDU_PDU_OFF];
}
else
{
eStatus = MB_EIO;
}
EXIT_CRITICAL_SECTION( );
return eStatus;
}
重点关注这个语句:pucFrame = ( UCHAR * ) & ucASCIIBuf[MB_SER_PDU_PDU_OFF];,这句话的意思是将形式参数的值进行改变。
当调用具体函数的时候eMBASCIIReceive( rcvaddress, pFrame, plen )的时候,首先将实参的值等于形参的值,然后函数体内又对形参值进行了改变,而实参pFrame并没有得到改变。如果将形参变量变成了UCHAR ** pucFrame,我们再来分析:
当函数调用的时候,变成了eMBASCIIReceive( rcvaddress, pFrame, &plen );那么
pucFrame = &pFrame;
在函数体内,pucFrame 指向pFrame。对*pucFrame 进行修改,就是对pFrame的值进行修改。
所有,这儿要传递地址必须采用指向指针的指针才形。
用户557863 2008-4-25 20:08
用户10415 2008-3-15 16:50
用户129951 2008-1-22 20:19
顶
用户88114 2007-9-30 15:51
楼主是做的什么题目啊?
郁闷!我也是成功参赛奖。
用户93051 2007-9-21 23:19
我得的是 终身遗憾奖 哈哈
很遗憾没参加
用户93841 2007-9-21 20:11