Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何读取大小不为';t是4的倍数_C - Fatal编程技术网

C 如何读取大小不为';t是4的倍数

C 如何读取大小不为';t是4的倍数,c,C,我正在读取文件*stl中的结构,但结构是: typedef struct { float x; float y; float z; } point; typedef struct { point normal_vector; //12 bytes point p1; //12 bytes point p2; //12 bytes point p3; //12 bytes short int notuse; //2 bytes }

我正在读取文件*stl中的结构,但结构是:

typedef struct
{
    float x;
    float y;
    float z;
} point;
typedef struct 
{
    point normal_vector; //12 bytes
    point p1; //12 bytes
    point p2; //12 bytes
    point p3; //12 bytes
    short int notuse; //2 bytes
} triangle;
sizeof(三角形)
是52-12+12+12+12+2+…2(我不知道最后2个是从哪里来的?)文件*stl中每个单元的大小是50(不是4的倍数)

如何将读取文件的结构大小减小(从52减小到50)


谢谢。

由于填充,将额外增加两个字节。填充是将结构与4字节边界对齐(您的字大小可能是32位,64位可能有所不同)

在文件中,每个结构存储了50个字节。因此,您可以读取这50个字节,并从50个字节中逐个为每个成员分配值。代码看起来像

Char readbuf[50];

//Read the 50 bytes into the buffer readbuf.

 triangle t;

 t.normal_vector.x  = (float *)readbuf;
 t.normal_vector.y  = (float *)(readbuf + sizeof(float));
 t.normal_vector.z  = (float *)(readbuf + 2*sizeof(float));
 t.p1.x             = (float *)(readbuf + 3*sizeof(float));

//and so on for other members.

请注意,这有字节对齐问题,同一程序可能无法在big-endian机器上运行。因此,请注意在没有任何规则或编码的情况下直接存储二进制数据。

使用GCC/G++可以这样做来打包您的结构:

typedef struct 
{
    point normal_vector; //12 bites
    point p1; //12 bites
    point p2; //12 bites
    point p3; //12 bites
    short int notuse; //2 bites
} __attribute__((packed)) triangle;

这是一种优于读取结构的方法——正如您所看到的,结构的内存布局可能会有所不同——并且减少其大小可能是一种方法

也就是说,您可以读取大数据块中的文件,并将数据剪切到所需的部分。然后逐个字段读取数据,并将数据放入目标数组中。差不多

float read_float(void ** data) {
    float ** fp = data;
    float ret = **fp; (*fp)++;
    return ret;
}

point read_point(void ** data) {
    point ret;
    ret.x = read_float(data);
    ret.y = read_float(data);
    ret.z = read_float(data);
    return ret;
}

int16_t read16(void ** data) {
    int16_t ** i16p = data;
    int16_t ret = **i16p; (*i16p)++;
    return ret;
}

point read_triangle(void ** data) {
    triangle ret;
    ret.normal_vector = read_point(data);
    ret.p1 = read_point(data);
    ret.p2 = read_point(data);
    ret.p3 = read_point(data);
    ret.notuse = read_int16(data); // using short int is not portable as well as its size could vary...
    return ret;
}

void * scursor = source_array; // which would be a char array
while (scursor < source_array + sizeof(source_array)) {
    // make sure that there are enough data present...
    target[tcursor++] = read_triangle(&scursor); // the scursor will be advanced by the called function.
}
float读取\u float(无效**数据){
浮点**fp=数据;
浮点ret=**fp;(*fp)+;
返回ret;
}
点读取点(无效**数据){
点ret;
ret.x=读取浮点数(数据);
ret.y=读取浮点数(数据);
ret.z=读取浮点数(数据);
返回ret;
}
int16\u t read16(无效**数据){
int16_t**i16p=数据;
int16_t ret=**i16p;(*i16p)+;
返回ret;
}
点读取三角形(无效**数据){
三角网;
ret.normal_矢量=读取点(数据);
ret.p1=读取点(数据);
ret.p2=读取点(数据);
ret.p3=读取点(数据);
ret.notuse=read_int16(data);//使用短int是不可移植的,因为它的大小可能会有所不同。。。
返回ret;
}
void*scursor=源数组;//这将是一个字符数组
while(scursor

这种方法也可以用于保持e。G您的数字的尾数是相同的——对于要在平台之间交换的文件,最好是大尾数。对
read16
的更改会很小,对
read\u float
的更改会大一些,但仍然可行。

您需要指示编译器打包结构。如何做到这一点的细节是特定于编译器的-RTFM:)处理器喜欢在已知块大小的情况下到处乱扔东西。有点变化无常,但它很乐意这样做@HansPassant-ugh-magic number+如果一次读取多个数组/vector.Hmm,则没有帮助。不,不是一个幻数,它是文件的记录大小。那个魔咒是很久以前施的。bizarro包装指令很神奇。当然,for()循环对数组没有问题。@gigigi——为什么要分配“fp”和“i16p”?他们似乎不习惯。你说的“相同”是什么意思?在您的解决方案中,文件中数据的解释仍将取决于平台。在小端结构上读取大端格式的文件将给出错误的结果。@willus(或者我应该叫你wiius?:-)现在它们被使用了,谢谢你指出。现在,解释确实依赖于平台,但实现平台独立的道路现在非常短。对不起。我用的是iPad,字体很小,我的眼睛也不像以前了。请随时打电话给我(Wiius!:)顺便说一句,为什么评论系统有时似乎不接受一行开头的“@username”?@willus根据我的经验,如果你评论一个答案,而回答者还没有评论,他不会自动被接受,因为他会得到通知。非常感谢,我刚刚通过了这个