с проблемой memcpy - PullRequest
       3

с проблемой memcpy

3 голосов
/ 06 июля 2010
char *a=NULL;

char *s=NULL; 

a=(char *)calloc(1,(sizeof(char))); 

s=(char *)calloc(1,(sizeof(char))); 

a="DATA"; 

memcpy(s,a,(strlen(a))); 

printf("%s",s);

Можете ли вы сказать мне, почему его печать DATA½½½½½½½½ ■ ε ■ ???? Как печатать только DATA ??Спасибо

Ответы [ 6 ]

6 голосов
/ 06 июля 2010

Строки в C заканчиваются нулевым символьным значением (nul).

strlen возвращает количество символов до нуля.

То есть вы не копируете ноль.

printf продолжает работать, печатая все, что находится в памяти после s, до тех пор, покадостигает нуля.

Вы также только создаете буфер размером 1, поэтому вы записываете данные поверх того, что находится после s, и вы теряете память calloc'd до a, прежде чем вы установите a как литерал.

Выделите память для s после нахождения длины строки, выделив еще один байт для включения нулевого терминатора, а затем скопируйте a в s.Вам не нужно выделять что-либо для a, как выглядит среда выполнения C после сохранения литерала "DATA".

2 голосов
/ 06 июля 2010

strlen считает только символы без терминатора '\ 0'. Без этого терминатора printf не знает конца строки.

Решение: тетсру (S, A, (STRLEN (а) +1));

2 голосов
/ 06 июля 2010

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

Кроме того, memcpy() не является функцией копирования строк, она не включает терминатор.Вы должны использовать strcpy().

. Наилучшим способом печати только ДАННЫХ может быть

puts("DATA");

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

1 голос
/ 06 июля 2010

Ваш

a="DATA";

удаляет указатель на выделенную память.Он не копирует «ДАННЫЕ» в память.Однако этого будет недостаточно для его хранения, поскольку

a=(char *)calloc(1,(sizeof(char))); 

выделяет один символ.В то время как

memcpy(s,a,(strlen(a)));

копирует то, что сейчас указано (строковый литерал "DATA"), в память, на которую указывает s.Но опять же, s указывает на один выделенный символ, а копирование более 1 символа приведет к перезаписи чего-либо и приведет к ошибке.

strlen(a) даст вам 4 (длина «DATA») и memcpyкопирует ровно 4 символаНо чтобы узнать, где заканчивается строка, C использует соглашение, чтобы поставить окончательный «нулевой» символ ('\ 0') в его конец.Таким образом, «DATA» в памяти представляет собой «D», «A», «T», «A», «0».

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

Чтобы скопировать строки, используйте вместо strcpy (или strncpy), он также копирует строку со своим последним нулевым байтом.(strcpy менее «безопасен», так как вы можете переполнить целевой буфер).

Но самая большая проблема, которую я вижу здесь, состоит в том, что вы резервируете один символ только для (и вы удаляете его тогда) иs, поэтому DATA \ 0 никуда не поместится.

1 голос
/ 06 июля 2010

Вам нужно сохранить завершающую \0 после этой строки DATA, чтобы printf() знал, что нужно остановить печать.

Вы можете заменить memcpy на strcat:

strcat(s, a);

должен это сделать.

Обратите внимание, что ранее была ошибка:

calloc(1,sizeof(char)) 

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

1 голос
/ 06 июля 2010

Вы резервируете пробел для 1 символа, поэтому вы фактически используете память какой-то другой переменной, когда пишете «ДАННЫЕ» (что составляет 4 символа + завершающий \0 для обозначения конца строки).

a=(char *)calloc(1,(sizeof(char)));

Для этого примера вам понадобится 5 или более символов:

a=(char *)calloc(5, (sizeof(char)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...