2013-11-25 3 views
0

Я пишу код очень низкого уровня для эмулирования «файловой системы» для домашнего проекта. Файловая система состоит из блоков фиксированного размера (1024B), но «файлу» разрешено охватывать несколько не последовательных блоков.Указатель Арифметика и чтение/запись в C

Мне нужно написать любой тип void *buf в файл с функцией, имитирующей write. Допустим, у нас есть следующая подпись: myWrite(int blockNum, void *buf, int nbytes.

Скажем, nbytes больше, чем 1024, поэтому мне приходится писать в несколько блоков. Так что я должен был бы сделать что-то вроде:

int remainder = nbytes - 1024; 
myWrite(firstBlock, buf, 1024); 
myWrite(nextBlock, (buf + 1024), remainder); 

myWrite вызывает стандартную функцию write снизу, проходя в подобных аргументов.

Проблема с арифметикой указателя, C не нравится, когда я выполняю арифметику указателя на void*. Я получаю EINVAL или EARGS (в зависимости от Mac против Linux), говорящий, что C не любит указатель, который я передал системному вызову write, так как он был создан с помощью арифметики указателей void.

Проблема в том, что я не знаю, какой тип данных я буду писать. Иногда это char *, а иногда это что-то обычное, как my_type *, которое представляет собой структуру из кода программы.

Есть ли способ обойти это? Мне нужно, чтобы обобщенная запись была такой. Моя текущая реализация работает большую часть времени, но иногда она терпит неудачу.

+1

Предполагая, что 'buf' объявлен как' void * ', а' 1024' - это количество байтов, тогда '(unsigned char *) buf + 1024' должно быть ОК. – ouah

+0

Будет ли это работать для любого типа данных? –

+2

Если вы просто пишете байты, базовый тип не имеет значения. – codnodder

ответ

2

Придерживайтесь использования void * -Примечания.

Когда потребность байта разумных арифметиков указателей возникает только бросить void * -указатель на char * (как sizeof(char) определена равный 1):

int a[2] = {47, 11}; 
void * p = &a[0]; 

printf("%d\n", *((int *)p)); /* Prints 47. */ 

p = ((char *) p) + sizeof(a[0]); /* Increments p by sizeof(int) bytes. */ 

printf("%d\n", *((int *)p)); /* Prints 11. */ 

Также как примечание ,: Чтобы ввести целые числа, описывающих объемы памяти или индексы используют size_t, так как гарантировано быть достаточно широким, чтобы адресовать/индексировать все на машине, на которой скомпилирован код.

2

Проблема с указателем арифметика, C не любит, когда я делаю арифметику указателей на void*

Это правильно: C запрещает вам добавлять целые числа к void*, потому что он не знает, как преобразовать число в число байтов, с помощью которого можно продвигать указатель. Обычно множитель может быть получен из типа указателя. void*, однако, не имеет типа, поэтому C запрещает арифметику.

C не против, если вы выполняете арифметику указателя на других типах указателей, где размер известен. Вы можете преобразовать ваш void* указатель на uint8_t* указатель, в char* указатель, или любой другой указатель типа, где sizeof(*ptr) равно 1, и делать арифметику на него прямо перед выполнением арифметических операций:

myWrite(nextBlock, ((char*)buf) + 1024, remainder); 

сами функции должны продолжать принимать void*.

Смежные вопросы