получить strlen после memcpy в c ++ - PullRequest
1 голос
/ 25 ноября 2011

Я пытаюсь объединить символы, используя функцию memcpy, однако, я получаю странную длину моего буфера после пары memcpy.см. код ниже

int main()
{
uint8 txbuffer[13]={0};
uint8 uibuffer[4] = "abc";
uint8 rxbuffer[4] = "def";
uint8 l[2]="g";
int index = 1;

cout << strlen((char*)txbuffer) <<endl;
memcpy(&txbuffer[1],&uibuffer, strlen((char*)uibuffer));
index+=strlen((char*)uibuffer);

cout <<"after first memcpy: "<< strlen((char*)txbuffer) <<endl;
memcpy(&txbuffer[index],&rxbuffer, strlen((char*)uibuffer));

cout <<"after second memcpy: "<< strlen((char*)txbuffer) <<endl;
memcpy(&txbuffer[0],&l, strlen((char*)l));

cout <<"after third memcpy: "<< strlen((char*)txbuffer) <<endl;
for (int i = 0; i < sizeof(txbuffer); i += 1)
{
    cout << (int(txbuffer[i]))<<" : "<< char(int(txbuffer[i]))<<endl;
}
return 0;
}

вывод:

after first memcpy: 0
after second memcpy: 0
after third memcpy: 7
103 : g
97 : a
98 : b
99 : c
100 : d
101 : e
102 : f
0 : 
0 : 
0 : 
0 : 
0 : 
0 :

мой вопрос: почему после первого memcpy strlen буфера все еще равен нулю?

Ответы [ 4 ]

2 голосов
/ 25 ноября 2011

Вы не должны strlen пункт назначения после memcpy извлечения strlen байтов из оригинала, поскольку вы не скопировали 0-терминатор.

Кроме того, вы копируете, начиная с байта 1, а не 0, что означает strlen, равное 0, потому что ваш массив изначально обнуляется (такой тип делает мой первый абзац неуместным, но вы должны знать об этом).

1 голос
/ 25 ноября 2011

Это потому, что первый символ в txbuffer является нулевым \0.(Вы инициализировали это таким образом.) Таким образом, строка при печати выдает нулевую длину.

Вы не перезаписали первый символ в первой или второй копии.Но вы, наконец, перезаписать его в 3-й копии.Вот почему длина равна нулю до 3-й копии.

//  Start
{  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0}

//  After 1st memcpy(): strlen() is still zero
{  0, 'a', 'b', 'c',   0,   0,   0,   0,   0,   0,   0,   0,   0}
   ^ first null character

//  After 2nd memcpy(): strlen() is still zero
{  0, 'a', 'b', 'c', 'd', 'e', 'f',   0,   0,   0,   0,   0,   0}
   ^ first null character

//  After 3rd memcpy(): strlen() is now 7
{'g', 'a', 'b', 'c', 'd', 'e', 'f',   0,   0,   0,   0,   0,   0}
                                      ^ first null character
0 голосов
/ 25 ноября 2011

здесь несколько вопросов.

Прежде всего использование & uibuffer в качестве аргумента для memcpy неверно, просто используйте uibuffer (rxbuffer,l), так как они уже являются адресами (будучи массивами):

memcpy(&txbuffer[1], uibuffer, strlen((char*)uibuffer));

выполнение strlen с указанным выше txbuffer (поскольку вы копируете в txtbuffer со смещением 1), даст длину 0, поскольку strlen считает до тех пор, пока не найдет \ 0, поэтому использование strlen в сочетании с memcpy не является хорошей идеей, вместо этого следите за длина, которая у вас есть в txtbuffer вручную, вы знаете длину строк, которые вы копируете, и смещения.

0 голосов
/ 25 ноября 2011

strlen() подсчитывает количество ненулевых байтов. Поскольку первоначальный NUL остается после копии, конечно strlen() возвращает ноль.

Вместо этого вы можете предпочесть использовать sizeof или более явную логику конкатенации:

int main()
{
    char txbuffer[13];
    char uibuffer[4] = "abc";
    char rxbuffer[4] = "def";
    char l[2]="g";
    int index = 1;

    int n = sprintf (txbuffer, "%s%s%s", uibuffer, rxbuffer, l);
    cout << "buffer has " << n << " bytes" << endl;
    return 0;
}
...