целочисленная арифметика на указатели в C - PullRequest
0 голосов
/ 11 августа 2010

Будет ли приведенный ниже оператор вычислять длину массива ???:

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++) = '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);
}

Ответы [ 2 ]

2 голосов
/ 11 августа 2010

Да, при условии, что результат помещается в байт - что из примера кода будет - и под «длиной массива» вы подразумеваете количество байтов минус заголовок пакета.

0 голосов
/ 11 августа 2010

Это даст вам количество байтов, добавленных функцией apple_Build_BundleSeedIDPrefToken().(Общее количество байтов, которые были заполнены в массиве UART_BUF[], на единицу больше, так как этот оператор не будет считать байт при UART_BUF[0].)

В общем случае вычитание двух указателейтип T * в массив элементов типа T дает вам разницу как число элементов (а не количество байтов).(Результат не определен, если один из двух указателей не указывает ни на элемент в одном и том же массиве, ни на элемент сразу после последнего.) Сам результат имеет целочисленный тип со знаком ptrdiff_t, который определен в<stddef.h>.

Однако здесь оба указателя указывают на один и тот же массив unsigned char, поэтому каждый элемент по определению является байтом.

Итак, выражение lcl_ptr - (unsigned char *)&UART1_BUF[1] будетукажите количество байтов, добавленных функцией.(Обратите внимание, что &UART_BUF[1] уже имеет тип unsigned char *, поэтому приведение внутри выражения не нужно.)

Это выражение затем приводится к unsigned char, что теоретически может усечь результат, хотя онов приведенном выше примере это явно не так.


Я отмечаю, что код немного странный, так как он присваивается UART_BUF[1] три раза!

  1. UART1_BUF[1] = 0x00; устанавливает значение 0;
  2. lcl_ptr = apple_Build_BundleSeedIDPrefToken(&UART1_BUF[1]); устанавливает значение 0x0D внутри вызываемой функции;
  3. UART1_BUF[1] = (unsigned char)(lcl_ptr - (unsigned char *)&UART1_BUF[1]); устанавливает значение 0x0E, поскольку функция добавляет 14 байтов.

В общем, помните, что нужно быть осторожным с вычитаниями указателя: ожидать, что они всегда дадут количество байтов, является распространенной ошибкой ...

#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;
}

дает (вклсистема, в которой sizeof(int)==4):

Difference (as int *): 2
Difference (as char *): 8
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...