получить strlen после memcpy в С++

Я пытаюсь объединить символы, используя функцию 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 буфера по-прежнему равен нулю?


person Carlitos Overflow    schedule 24.11.2011    source источник


Ответы (4)


Это связано с тем, что первый символ в 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
person Mysticial    schedule 24.11.2011

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

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

person Michael Krelin - hacker    schedule 24.11.2011

strlen() подсчитывает количество байтов, отличных от NUL. Поскольку исходный 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;
}
person wallyk    schedule 24.11.2011

здесь есть несколько проблем.

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

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

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

person AndersK    schedule 24.11.2011