Почему memcpy не работает при копировании массива символов в структуру?

#define buffer 128    

int main(){
  char buf[buffer]="";

  ifstream infile("/home/kevin/Music/test.mp3",ios::binary);
  infile.seekg(-buffer,ios::end);
  if(!infile || !infile.read(buf,buffer)){
      cout<<"fail!"<<endl;
  }
  ID3v1 id3;
  cout<<sizeof(id3)<<endl;
  memcpy(&id3,buf,128);
  cout<<id3.header<<endl;
}


struct ID3v1{
  char header[3];
  char title[30];
  char artist[30];
  char album[30];
  char year[4];
  char comment[28];
  bool zerobyte;
  bool track;
  bool genre;

};

Когда я делаю memcpy, кажется, что в поле заголовка помещается слишком много данных. Нужно ли мне просматривать каждый из членов структуры и копировать данные? Я также использую С++, но это больше похоже на стратегию «С». Есть ли лучший способ для С++?


person carboncomputed    schedule 10.03.2012    source источник
comment
Вы не можете «запихнуть больше данных» в char[3], вы можете прочитать слишком много, потому что он не завершается нулем.   -  person Hans Passant    schedule 11.03.2012
comment
Ваш ID3v1.header, скорее всего, не заканчивается нулем. Вы печатаете все до \0.   -  person lapk    schedule 11.03.2012
comment
Я настоятельно рекомендую вам не называть свой буфер и размер буфера buf и buffer. Почему бы не назвать одного buf, а другого bufSize? Или buffer и bufferSize? Это смущает! Кроме того, если все, что вы хотите скопировать, это тег ID3 и его размер равен 128, замените все 128 константой со значимым именем, например ID3TAG_SIZE или любым другим.   -  person hochl    schedule 11.03.2012
comment
Чтобы добавить к 111111, вы уверены, что данные, которые вы получаете в этой c-строке, - это то, что вам нужно?   -  person Adam Reed    schedule 11.03.2012
comment
Да, я думаю, что это так, потому что данные верны для остальной части ввода. Я следил за тем, чтобы правильно использовать memcpy, я никогда не использовал его раньше, но данные тега не завершаются нулем.   -  person carboncomputed    schedule 11.03.2012
comment
@hochi Да, я собирался переименовать его, просто немного кода, собранного вместе, не задумываясь, однако, спасибо за совет.   -  person carboncomputed    schedule 11.03.2012


Ответы (3)


Как отмечено во всех комментариях (вам не хватает символа «\ 0», или при печати C-String оператор ‹‹ ожидает, что последовательность символов будет завершена «\ 0»).

Пытаться:

std::cout << std::string(id3.header, id3.header+3) << std::endl;

Это напечатает три символа в поле заголовка.

person Martin York    schedule 10.03.2012

Проблема, скорее всего, в том, что memcpy делает то, что делает.

Он копирует 128 байт в вашу структуру.

Затем вы пытаетесь распечатать заголовок. Он печатает 1-й символ, 2-й, 3-й... и продолжает печатать, пока не найдет '\0' (символ окончания строки).

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

person Milan    schedule 10.03.2012

другие проблемы, с которыми вы можете столкнуться при использовании memcpy:

  • ваши элементы структуры могут быть выровнены компилятором по границам слов. у большинства компиляторов есть некоторая прагма или переключатель командной строки, чтобы указать используемое выравнивание.
  • некоторые процессоры требуют сохранения коротких или длинных слов на границах слов, в этом случае изменение выравнивания вам не поможет, так как вы не сможете читать с невыровненных адресов.
  • если вы копируете целые числа больше, чем char (например, короткие или длинные), вы должны обязательно исправить порядок байтов в зависимости от архитектуры вашего процессора.
person Willem Hengeveld    schedule 10.03.2012