如何解决将数据分配给char数组
我正在用C进行代码编写有关块存储的分配(对于OS类)。我的结构(在另一个文件中typedef为block_store_t)是
struct block_store{
unsigned char data[BLOCK_SIZE_BYTES][BLOCK_STORE_NUM_BLOCKS];
//block_size_bytes is 32,block_store_num_blocks is 512
};
我将所有数据放入char数组中,因为char是一个字节长。为了跟踪正在使用的块,我们使用了位图,必须将其存储在块存储数据数组的块127中。因此,访问它应该类似于
bs->data[127]
或类似的东西。我在其中声明初始化块存储结构的代码如下:
block_store_t *block_store_create()
{
bitmap_t *bm = bitmap_create(BITMAP_SIZE_BITS);
block_store_t *bs = malloc(sizeof(block_store_t));
if (bs == NULL) return NULL;
for (int i = 0; i < (BITMAP_SIZE_BLOCKS); i++)
{
bitmap_set(bm,i + BITMAP_START_BLOCK);
}
//I've tried the ways two ways below,both give seg faults
//bs->data[BITMAP_START_BLOCK] = (unsigned char*)*bm;
//memcpy(bs.data[BITMAP_START_BLOCK],bm,BITMAP_SIZE_BYTES);
return bs;
}
由于位图的类型为bitmap_t,如何获取位图位于数据数组的块127中,又如何再次访问它?如果位图大于一个块的大小(在我的情况下,位图将是两个块的大小,因为每个块512位/ 8/32字节)怎么办?
tl; dr如何将不是char的数据分配给结构内部的char数组?我正在使用char,因为它长一字节。
解决方法
如何将不是char的数据分配给结构内部的char数组?我正在使用char,因为它长一字节。
您不能分配(这意味着使用=
运算符)将结构类型的对象更改为类型unsigned char
的对象。如果您的bitmap_t
是数字类型,则可以进行这种分配,但是除非它是字符类型,否则结果将丢失数据。您根本无法分配整个数组(与分配给非数组类型的数组元素相反)。
但是,您可以将对象表示形式的字节复制到字符数组中。为此,您的memcpy()
方法基本上是正确的:
//memcpy(bs.data[BITMAP_START_BLOCK],bm,BITMAP_SIZE_BYTES);
尤其要注意,bs.data[BITMAP_START_BLOCK]
指定的值是unsigned char
的数组,因此,它会自动转换为指向该数组第一个元素的指针,该指针将位于与BITMAP_START_BLOCK * BLOCK_STORE_NUM_BLOCKS
的开头相距bs.data
个字节的偏移量。
但是该偏移量表达式使我认为您对block_store结构的定义与您打算的有所不同。这个...
unsigned char data[BLOCK_SIZE_BYTES][BLOCK_STORE_NUM_BLOCKS];
...将data
声明为BLOCK_SIZE_BYTES
元素的数组,每个元素都是类型为BLOCK_STORE_NUM_BLOCKS
的{{1}}元素的数组。我认为您已经颠倒了尺寸。与宏名称一致的声明为:
unsigned char
unsigned char data[BLOCK_STORE_NUM_BLOCKS][BLOCK_SIZE_BYTES];
的字节大小是相同的,但是data
的含义彼此不同。使用后一种声明bs.data[BITMAP_START_BLOCK]
,您在data
中产生的偏移量将是memcpy
开头的BITMAP_START_BLOCK * BLOCK_SIZE_BYTES
个字节,我认为这是您想要的。>
我将如何再次访问它?
如果您打算仅依靠语言标准定义的行为,则可以将位图复制回data
类型的对象:
bitmap_t
但是请注意,所涉及的副本是 shallow 。如果要复制的对象包含指针,那么将要复制的是指针,而不是它们指向的数据。
不符合要求的替代方法
C的所谓“严格别名规则”禁止访问您的bitmap_t bm2;
memcpy(&bm2,bs.data[BITMAP_START_BLOCK],BITMAP_SIZE_BYTES);
或其struct block_store
成员,就好像其中一部分是data
。但是,从历史上看,这种访问是相对普遍的做法。这将采用强制转换块或字节指针的形式,以键入bitmap_t
并取消引用结果。例如:
bitmap_t *
这种方法的优点是表达式更简单,复制更少,但是您的编译器可以使用此类代码自由地执行许多令人惊讶的事情。在走那条路线之前,请确保您知道如何防止编译器在这方面感到惊讶。例如,对于GCC,您需要为编译器指定// requires a definition of bitmap_t in scope:
(bitmap_t *) bs.data[BITMAP_START_BLOCK] = *bm;
bitmap_set((bitmap_t *) bs.data[BITMAP_START_BLOCK],x);
选项。
取决于os。
您需要在此处处理对齐方式,而这没有任何标准。
对于gcc和msvc就像这样
#include <stdio.h>
#include <stddef.h>
int main(int argc,char *argv[])
{
struct blockheader {
#pragma pack(1)
unsigned char hashPrevBlock[30];
unsigned short b; //2 bytes
unsigned char merk[72];
};
unsigned char c[104] = {0};
struct blockheader *a = (struct blockheader *)c;
a->b = 400 ;
printf("and then %d,%d\n",a->b,offsetof(struct blockheader,b));
}
对于阵列的批量加载部分,您可以使用offsetof
来确定大小和起点。
gcc本机样式是
struct blockheader_on_gcc {
unsigned char hashPrevBlock[30];
unsigned short b; //2 bytes
unsigned char merk[72];
}__attribute__((aligned(1)));
如果在末尾有多余的字节是np。
如果有问题,可以使用__attribute__((packed))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。