integer arithmetic on pointers in C
Will the statement below calculate the length of the array???:
UART1_BUF[1] = (unsigned char)(lcl_ptr - (unsigned char *)&UART1_BUF[1]);
/////////////////////////////////////////////////////////////////////////////////////
unsigned char UART1_BUF[128];
void apple_Build_SetFIDTokenValues(void)
/* apple_Build_SetFIDTokenValues -
*
* This function builds the apple protocol StartIDPS() command.
*/
{
unsigned char * lcl_ptr;
UART1_BUF[0] = BT_START_OF_PACKET;
UART1_BUF[1] = 0x00;
//BundleSeedIDPrefToken
lcl_ptr = apple_Build_BundleSeedIDPrefToken(&UART1_BUF[1]);
UART1_BUF[1] = (unsigned char)(lcl_ptr - (unsigned char *)&UART1_BUF[1]);
*lcl_ptr = apple_checksum((unsigned char *)UART1_BUF, UART1_BUF[1]);
UART1_BUF[UART1_BUF[1]] = *lcl_ptr;
}
unsigned char * apple_Build_BundleSeedIDPrefToken(unsigned char *buf_ptr)
{
*(buf_ptr++) = 0x0D; //length of BundleSeedIDPrefToken minus this byte
*(buf_ptr++) = BundleSeedIDPref_Token_FID_TYPE;
*(buf_ptr++) = BundleSeedIDPref_Token_FID_SUBTYPE;
//BundleSeedIDString
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = 开发者_JS百科'0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
*(buf_ptr++) = '0';
return (buf_ptr);
}
Yes, provided that the result fits in a byte - which, from the code sample, it will - and, by 'length of the array', you mean the number of bytes minus the packet header.
It will give you the number of bytes added by the apple_Build_BundleSeedIDPrefToken()
function. (The total number of bytes that have been filled in the UART_BUF[]
array is one more than that, because that statement won't count the byte at UART_BUF[0]
.)
In general, subtracting two pointers of type T *
into an array of elements of type T
gives you the difference as the number of elements (rather than the number of bytes). (The result is undefined if either of the two pointers do not point to either an element within the same array, or the element just past the last one.) The result itself has a signed integer type, ptrdiff_t
, which is defined in <stddef.h>
.
However, here, both pointers are pointing into the same array of unsigned char
, so each element is a byte by definition.
So, the expression lcl_ptr - (unsigned char *)&UART1_BUF[1]
will give the number of bytes added by the function. (Note that &UART_BUF[1]
is of type unsigned char *
already, so the cast inside the expression is unnecessary.)
That expression is then cast to unsigned char
, which could in theory truncate the result, although it clearly doesn't in the above example.
I note that the code is a little odd, in that it assigns to UART_BUF[1]
three times!
UART1_BUF[1] = 0x00;
sets it to 0;lcl_ptr = apple_Build_BundleSeedIDPrefToken(&UART1_BUF[1]);
sets it to0x0D
inside the called function;UART1_BUF[1] = (unsigned char)(lcl_ptr - (unsigned char *)&UART1_BUF[1]);
sets it to0x0E
, as the function adds 14 bytes.
More generally, remember to be careful with pointer subtractions: expecting them to always give a number of bytes is a common mistake...
#include <stdio.h>
#include <stddef.h>
int main(void)
{
int array[4];
int *start, *end;
start = &array[1];
end = &array[3];
printf("Difference (as int *): %d\n", end - start);
printf("Difference (as char *): %d\n", (char *)end - (char *)start);
return 0;
}
gives (on a system where sizeof(int)==4
):
Difference (as int *): 2
Difference (as char *): 8
精彩评论