我正在编写一些非常低级的C代码来模拟家庭作业项目的“文件系统”。文件系统由固定大小的块(1024B)组成,但允许“文件”跨越多个非连续的块。
我需要能够将任何类型的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
函数,传入类似的参数。
问题在于指针算术,当我在void*
上进行指针算术时,C不喜欢。我得到一个EINVAL
或EARGS
(取决于Mac与Linux),说C不喜欢我传递给write
系统调用的指针,因为它是通过{{1指针算术。
问题是,我不知道我将写什么样的数据类型。有时它是void
,有时它是自定义的,如char *
,代表程序代码中的结构。
这有什么办法吗?我需要像这样的通用写。我当前的实现大部分时间都在工作,但有时会失败。
答案 0 :(得分:2)
问题在于指针算术,当我在
void*
上进行指针算术时,C不喜欢
这是正确的:C禁止你向void*
添加整数,因为它不知道如何将数字转换为推进指针的字节数。通常,乘数可以从指针的类型导出。但是,void*
没有类型,因此C禁止对其进行算术运算。
C不介意你是否对已知大小的其他指针类型进行指针运算。您可以将void*
指针转换为uint8_t*
指针,char*
指针或指向sizeof(*ptr)
等于1
的类型的任何其他指针,并且在进行算术运算之前对它进行算术运算:
myWrite(nextBlock, ((char*)buf) + 1024, remainder);
这些功能本身应该继续void*
。
答案 1 :(得分: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
,因为它保证足够宽,可以解决/索引代码编译的机器上的所有内容。