Двоичные от 0000 до FFFF с использованием C - PullRequest
1 голос
/ 01 февраля 2010

Я пытаюсь программировать, используя C, чтобы записать двоичные данные в файл .bin и просто выполнить итерацию для записи от 0000 до FFFF. Я подумал, что буду использовать fopen с тэгом 'wb', а затем смогу записывать двоичные данные, но я не уверен, как перебрать 0000 - FFFF с помощью C. Спасибо за любую помощь.

Вот мой код сейчас:

#include <stdio.h>
#include <stdlib.h>

int main()
{
 FILE *f = fopen("binary.bin", "wb");
 unsigned long i;

 //if(f == NULL) { ...error handling... }

 for(i = 0x0000; i <= 0xFFFF; i++){
  // Write something to the file, e.g. the 16-bit (2 byte) value of "i"
  unsigned short someData = i;
  fwrite(&someData, 1, 2, f);
 }

 fclose(f);
 return 0;
 //printf("Hello World\n");
 getchar();
}

Это выдаст 00 00 01 00 02 00 ...

Вот мой вопрос сейчас. Разве это не должно считывать 00 00 00 01 00 02 ... Разве в начале не должно быть лишних «00»?

Кроме того, я пытался понять, как я могу скопировать и расширить его, сделав его 0000 0000 0001 0001 и т. Д.? [Обновление: я просто скопировал строку fwrite и сделал это снова, и это решило эту проблему]

Ответы [ 6 ]

8 голосов
/ 01 февраля 2010

Это простой пример записи некоторых двоичных чисел в файл.

FILE *f = fopen("yourfile", "wb");

if(f == NULL) { ...error handling... }

for(unsigned long i = 0x0000; i <= 0xFFFF; ++i)
{
    // Write something to the file, e.g. the 16-bit (2 byte) value of "i"
    unsigned short someData = i;
    fwrite(&someData, 1, 2, f);
}

fclose(f);

Обратите внимание, что переменная i здесь должна быть больше 16-битной, чтобы не оборачиваться (см. Мои комментарии к другим ответам) Тип long гарантирует размер не менее 32 бит.

5 голосов
/ 01 февраля 2010
for (int i = 0x0000; i <= 0xffff; ++i)
3 голосов
/ 01 февраля 2010

Для цикла от 0 до 0xffff, оба включительно, вы делаете:

for (i=0; i <= 0xffff; ++i)

Теперь первый интересный вопрос: какой тип i? В C гарантируется, что unsigned int будет содержать значения в диапазоне [0, 0xffff], что означает, что i <= 0xffff всегда будет истинным для unsigned int i;, если UINT_MAX равно 0xffff. поэтому i не может быть типом размера, меньшим или равным unsigned int. long или unsigned long - это наименьший тип, который может хранить 0xffff + 1 в портативном режиме. Итак, нам нужно, чтобы i был типа unsigned long или long. В C99 вы можете упростить задачу, включив stdint.h, а затем используя uint32_t type.

Второй интересный вопрос: что вы хотите написать? Будет ли макет вашего файла:

00 00 00 01 00 02 00 03 00 04 00 05 00 06 00 07
...
FF F8 FF F9 FF FA FF FB FF FC FF FD FF FE FF FF

или вы хотите записать значения в файл, используя ваш любимый тип данных выше, а затем сможете быстро их снова прочитать? Например, если int равен 32 битам, а ваша система имеет младший порядок, запись этих значений даст вам файл, такой как:

00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ...

Если вы хотите первое, вы должны убедиться, что вы записываете два байта на число в правильном порядке, и что порядковый номер вашей ОС не влияет на вывод. Самый простой способ сделать это, вероятно, что-то вроде этого:

for (i=0; i <= 0xff; ++i) {
    unsigned char values[2];
    values[0] = (i & 0xff00) >> 8;
    values[1] = i & 0xff; 
    fwrite(values, 1, 2, fp); 
}

Если вы хотите второе, ваша жизнь станет проще, особенно если вам не важен порядок байтов:

for (i=0; i <= 0xff; ++i) {
    fwrite(&i, sizeof i, 1, fp);
}

запишет ваши значения, чтобы вы могли читать их обратно в той же системе с той же переменной типа.

2 голосов
/ 01 февраля 2010
for (i = 0x0000; i <= 0xFFFF; ++i)
0 голосов
/ 14 декабря 2011

Альтернативный метод для переносимой записи байтов в стиле с прямым порядком байтов: проверьте htons и htonl (и их обратные значения).

Они конвертируют из любого формата, который использует ваша машина (чипы Intel имеют младший порядок, как указывалось несколькими людьми), в «сетевой» порядок (big endian). htons делает это в 16-битных словах; htonl в 32-битных словах. В качестве дополнительного преимущества, если ваша программа находится на компьютере с Big Endian, они компилируются в no-ops. Они определяются в <arpa/inet.h> или <netinet/in.h>, в зависимости от системы.

BSD (и Linux) также предоставляют набор (ы) подпрограмм, называемых такими вещами, как htobe16 (16-разрядный хост с прямым порядком байтов) в <endian.h>.

Они также помогают сэкономить на записи одного байта за раз.

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

{
  unsigned int x = 0xdead;
  unsigned char hi = (x & 0xff00) >> 8;
  unsigned char lo = (x & 0x00ff);
}
{
  unsigned long int x = 0xdeadbeef;
  unsigned char by0 = (x & 0xff000000) >> 24;
  unsigned char by1 = (x & 0x00ff0000) >> 16;
  unsigned char by2 = (x & 0x0000ff00) >> 8;
  unsigned char by3 = (x & 0x000000ff);
}

(Похоже, gcc достаточно умен, чтобы выполнить оптимизацию вне подразделения, хотя ... приятно.)

0 голосов
/ 01 февраля 2010

Чтобы контролировать Endianess вашего вывода, вы должны будете написать байты (октеты) самостоятельно:

for (unsigned int i = 0; // Same as 0x0000
     i <= 0xFFFF;
     ++i)
{
  unsigned char c;
  c = i / 256; // In Big Endian, output the Most Significant Byte (MSB) first.
  fputc(/*...*/);
  c = i % 256;
  fputc(/*...*/);
}

Это предпочтительный метод, когда файл должен быть Big Endian. Это обеспечит порядок байтов независимо от порядка процессора. Это также можно настроить для вывода на Little Endican.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...