0

Работаю с android jni. В цикле получаю код символа.Имеем

char* buf = (char*) malloc(sizeof(char));

нужно в buf скопировать символ с кодом например 100.Пробовал через memcpy и memmove но не могу понять как.

int code = 100;
memcpy(buf, &code, 1);

вылетает приложение непонятно почему.Как скопировать символ по его коду в buf?

Ivan
  • 556
  • 2
  • 14
  • для примера написал 100 – Ivan Jun 10 '18 at 08:34
  • Где-то в другом месте вылетает. С тем memcpy, что вы написали в вопросе все нормально – avp Jun 10 '18 at 10:15
  • я его просто уже исправил из ответа ниже – Ivan Jun 10 '18 at 10:18
  • Зачем тут вообще memcpy? Откуда взялась идея копировать один символ через memcpy? – AnT stands with Russia Jun 10 '18 at 14:32
  • с интернета взялаь.А как мне еще строку собрать? – Ivan Jun 10 '18 at 14:33
  • Обычный опрепатор присваивания запишет вам один символ туда, куда скажете. – AnT stands with Russia Jun 10 '18 at 14:34
  • нужно к строке неизвестной длины(изначально 0) прибавить посимвольно. – Ivan Jun 10 '18 at 14:35
  • Зачем такие сложности, при такой размерности делается так buf[0] = (unsigned)code;, что б не было "расширения по знаку" я добавил unsigned. Поведение будет аналогично правильно-записаному memcpy. – nick_n_a Jun 14 '18 at 07:20

3 Answers3

2

Синопсис

#include <string.h>
void *memcpy(void * restrict s1, void * restrict s2, size_t n);

Описание

Функция memcpy копирует n символов из объекта, на который указывает s2, в объект, на который указывает s1. Если копирование происходит между перекрывающимися объектами, поведение не определено.

Второй аргумент memcpy — это адрес источника, а не сам источник. А у вас получается так, что memcpy пытается получить значение из адреса 100, что приводит к падению приложения.

Попробуйте так:

char* buf = (char*) malloc(sizeof(char));
int code = 100;

const char ch = (char) code;
memcpy(buf, &ch, 1);

Кстати, вам обязательно нужно использовать memcpy? Почему бы не сделать так:

*buf = (char) code;

Примечания

  1. sizeof(char) по стандарту равен 1:

    When sizeof is applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1.

    Так что можно писать char *buf = (char *) malloc(1);.

  2. Приводить возвращаемое значение malloc к определенному типу не нужно. См. этот вопрос. Так что лучше будет писать char *buf = malloc(sizeof *buf);.
eanmos
  • 6,651
  • Про функцию знаю.Делал так.В общем я побайтно читаю файл.Имею int code.Так вот нужно code скопировать. – Ivan Jun 10 '18 at 08:32
  • Ну приведите int к char (если у вас однобайтная кодировка). – eanmos Jun 10 '18 at 08:34
  • По всякому делал.(char) code – Ivan Jun 10 '18 at 08:36
  • Я же говорю, что делать вот так: memcpy(buf, (char) 100, 1) нельзя. Т. к. второй аргумент memcpy должен быть адресом источника, а не самим источником. А у вас получается так, что memcpy получает значение из адреса 100, что приводит к падению приложения. – eanmos Jun 10 '18 at 09:00
  • вопрос дополнил как я делаю – Ivan Jun 10 '18 at 09:02
  • @Ivan, скомпилировал в ideone (ссылка). – eanmos Jun 10 '18 at 09:11
  • Спасибо.char ch = (char) code придется использовать в цикле.Не будет перерасход памяти? – Ivan Jun 10 '18 at 09:30
  • @Ivan, Был рад помочь :) Перерасхода, конечно не будет. Если вам дан исчерпывающий ответ, отметьте его галочкой (слева от ответа). – eanmos Jun 10 '18 at 09:33
  • Для моих целей лучше memmove или memcpy? – Ivan Jun 10 '18 at 09:58
  • @Ivan, Для ваших целей лучше *buf = (char) code. А вообще, разница между memmove и memcpy в том, что первая позволяет копировать перекрывающиеся области памяти, следовательно memmove зачастую медленнее, чем memcpy. – eanmos Jun 10 '18 at 10:01
  • *buf = (char) code не пойдет.Мне нужно считать все байты в одну строку – Ivan Jun 10 '18 at 10:03
  • @Ivan, что memcpy, что memmove, что *buf = code в конечном счете просто поместят символ в buf. Так что все три способа делают одно и то же. Следовательно, вам должны подойти все три способа. – eanmos Jun 10 '18 at 10:05
  • Что бы к buf прибавить еще символы нужно memcpy(buf + strlen(buf), &ch, 1); верно? – Ivan Jun 10 '18 at 10:06
  • @Ivan, если вам нужно считать содержимое файла в строку, то посмотрите этот вопрос (обратите внимание на комментарий @avp к ответу). Нет, ваш пример будет работать не верно: 1) Вы выделяете один байт для buf, следовательно большее кол-во байт просто не влезет; 2) strlen работает только для нуль-терминируемых строк. – eanmos Jun 10 '18 at 10:10
  • заждался в комнате – Ivan Jun 10 '18 at 10:38
  • Зачем так сложно то, проще: char but = (char)code; – NewView Jun 10 '18 at 13:03
  • @NewView, это долгая история :) См. чат – eanmos Jun 10 '18 at 13:14
1
int code = 100;
memcpy(&buf, &code, sizeof(char));

А вообще так еще проще

char a = (char)100;
-2

Вот что я хотел

char* buf = malloc(1);
int code = 100;
int l = 0;

memset(buf ,0,1);

for(int i = 0;i<10;i++){
    const char ch = (char) code + i;
    memcpy(buf + l, &ch, strlen(&ch));
    l++;
}
printf("%s\r\n", buf);
free(buf);
Ivan
  • 556
  • 2
  • 14
  • А вы не забыли о NULL символе в си строке? –  Jun 10 '18 at 14:25
  • Помню но он вроде тут и не нужен – Ivan Jun 10 '18 at 14:27
  • 3
    Это бессмыслица какая-то. Размер буфера - 1. Вы пишете туда 10 символов с вылетом за пределы выделенной памяти. Символа 0 в конце строки - нет. При чем и зачем здесь вообще memcpy с самого начала - не ясно. – AnT stands with Russia Jun 10 '18 at 14:30
  • Полностью согласен с @AnT. Да и копирование памяти тут совсем не нужно, можно разыменовать указатель с offset и записать туда символ... –  Jun 10 '18 at 14:30
  • На java будет так String s = "a";s = s + "b";.s стала ab.Нужно такое же на c для этого и нужно memcpy – Ivan Jun 10 '18 at 14:32
  • @LLENN покажите как – Ivan Jun 10 '18 at 14:33
  • @Ivan, вам нужно использовать strcpy. Только сначала прочитайте о C-строках (здесь, например). – eanmos Jun 10 '18 at 15:23
  • ок.На счет кодировки не подскажите?https://ideone.com/L4hu2q – Ivan Jun 10 '18 at 15:25
  • @Ivan, боже мой... Извините, если звучит грубо, конечно, но... вам же тысячу раз сказали, что в буфере не хватает места. Вы выделяете память под один элемент (malloc(--> 1 <--)), а записывает аж 10! – eanmos Jun 10 '18 at 15:30
  • @Ivan, что именно с кодировкой? – eanmos Jun 10 '18 at 15:31
  • Я переделывать буду.Вопрос если будет места хватать то русские символы будут нормально отображаться? – Ivan Jun 10 '18 at 15:32
  • Кракозябры.Нужно руский символ что бы был русским английский английским и т.д. – Ivan Jun 10 '18 at 15:32
  • @Ivan, про кодировки смотрите здесь. – eanmos Jun 10 '18 at 15:34
  • я не с консолью работаю – Ivan Jun 10 '18 at 15:35
  • До кодировок кажеться ещё рановато :) зачем в принципе выделять память? Статический буфер размером 11 вам поможет :) вместо memcpy: buf[I] = ch; в цикле for, после цикла: buf[10] = '\0' вместо memset: char buf[11] = {0}; – NewView Jun 10 '18 at 16:06
  • и l у вас по сути ровна i, лишняя она :) – NewView Jun 10 '18 at 16:12
  • Цикл for для примера дабы один и тот жк символ не выводить для этого и i – Ivan Jun 10 '18 at 17:40
  • Для примера взял 10.а так качаю с интернета файл неизвестной длины – Ivan Jun 10 '18 at 17:41