C 未修改的联合数组
我对以下代码有问题。它应该是一个简单的C 未修改的联合数组,c,arrays,pointers,unions,C,Arrays,Pointers,Unions,我对以下代码有问题。它应该是一个简单的.obj加载程序,将数据存储在三个不同的数组中。数组正在被传递到函数中,但它们没有被修改。线*out_顶点[索引]=gl_向量3_make(0.0,0.0,0.0)每次使用函数时也会抛出一个EXC\u BAD\u访问,即使我预先分配了传入的数组并删除了函数本身中所有相关的分配代码 目标h #ifndef ObjectIO_h #define ObjectIO_h union _vector2 { struct {float x, y;};
.obj
加载程序,将数据存储在三个不同的数组中。数组正在被传递到函数中,但它们没有被修改。线*out_顶点[索引]=gl_向量3_make(0.0,0.0,0.0)
每次使用函数时也会抛出一个EXC\u BAD\u访问
,即使我预先分配了传入的数组并删除了函数本身中所有相关的分配代码
目标h
#ifndef ObjectIO_h
#define ObjectIO_h
union _vector2 {
struct {float x, y;};
struct {float s, t;};
float v[2];
};
typedef union _vector2 gl_vector2;
extern inline gl_vector2 gl_vector2_make(float x, float y);
union _vector3 {
struct {float x, y, z;};
struct {float s, t, p;};
struct {float r, g, b;};
float v[3];
};
typedef union _vector3 gl_vector3;
extern inline gl_vector3 gl_vector3_make(float x, float y, float z);
union _vector4 {
struct {float x, y, z, w;};
struct {float s, t, p, q;};
struct {float r, g, b, a;};
float v[4];
};
typedef union _vector4 gl_vector4;
extern inline gl_vector4 gl_vector4_make(float x, float y, float z, float w);
extern inline int loadOBJ(const char *path, gl_vector3 **out_vertices, gl_vector2 **out_uvs, gl_vector3 **out_normals);
#endif
目标c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ObjectIO.h"
extern inline gl_vector2 gl_vector2_make(float x, float y) {
gl_vector2 vector;
vector.x = x;
vector.y = y;
return vector;
}
extern inline gl_vector3 gl_vector3_make(float x, float y, float z) {
gl_vector3 vector;
vector.x = x;
vector.y = y;
vector.z = z;
return vector;
}
extern inline gl_vector4 gl_vector4_make(float x, float y, float z, float w) {
gl_vector4 vector;
vector.x = x;
vector.y = y;
vector.z = z;
vector.w = w;
return vector;
}
extern inline char** splitstring(char *inputstring, char *separator, size_t *lines) {
char **res = NULL;
char * p = strtok(inputstring, separator);
int n_spaces = 0, i;
while (p) {
n_spaces ++;
res = realloc(res, sizeof(char*) * n_spaces);
if (res == NULL)
exit (-1); /* memory allocation failed */
res[n_spaces - 1] = p;
p = strtok (NULL, separator);
}
res = realloc (res, sizeof (char*) * (n_spaces + 1));
res[n_spaces] = '\0';
/* print the result */
for (i = 0; i < (n_spaces); i ++) printf ("res[%d] = %s\n", i, res[i]);
/* free the memory allocated */
*lines = (n_spaces - 1);
free(res);
return res;
}
extern inline int loadOBJ(const char *path, gl_vector3 **out_vertices, gl_vector2 **out_uvs, gl_vector3 **out_normals) {
printf("Loading OBJ file %s...\n", path);
long filesize;
char *file_c;
char *linesep;
char **filecontents;
size_t filecontentsize, result, lines, index, faces;
float *normals = malloc(sizeof(float) * 3);
float *uvs = malloc(sizeof(float) * 2);
float *vertices = malloc(sizeof(float) * 3);
FILE* file = fopen(path, "r");
if (file == NULL) {
printf("File %s cannot be opened.\n", path);
fclose(file);
return 0;
}
fseek(file, 0, SEEK_END);
filesize = ftell(file);
fseek(file, 0, SEEK_SET);
filecontentsize = sizeof(char) * filesize;
file_c = malloc(filecontentsize);
result = fread(file_c, 1, filesize, file);
linesep = malloc(sizeof(char) * 2);
linesep[0] = '\n';
lines = 0;
index = 0;
faces = 0;
filecontents = splitstring(file_c, linesep, &lines);
fseek(file, 0, SEEK_SET);
while (index < lines) {
if (filecontents[index][0] == 'v') {
if (filecontents[index][1] == 'n') {
normals = realloc(normals, (sizeof(float) * 3));
fscanf(file, "vn %f %f %f\n", &normals[(index * 3) + 0], &normals[(index * 3) + 1], &normals[(index * 3) + 2]);
}
else {
if (filecontents[index][1] == 't') {
uvs = realloc(uvs, (sizeof(float) * 2));
fscanf(file, "vt %f %f\n", &uvs[(index * 3) + 0], &uvs[(index * 3) + 1]);
}
else {
vertices = realloc(vertices, (sizeof(float) * 3));
fscanf(file, "v %f %f %f\n", &vertices[(index * 3) + 0], &vertices[(index * 3) + 1], &vertices[(index * 3) + 2]);
}
}
}
if (filecontents[index][0] == 'f') {
faces ++;
}
index ++;
}
*out_vertices = malloc(sizeof(gl_vector3) * faces * 3);
*out_uvs = malloc(sizeof(gl_vector2) * faces * 2);
*out_normals = malloc(sizeof(gl_vector3) * faces * 3);
index = 0;
while (index <= lines) {
*out_normals[index] = gl_vector3_make(0.0, 0.0, 0.0);
*out_uvs[index] = gl_vector2_make(0.0, 0.0);
*out_vertices[index] = gl_vector3_make(0.0, 0.0, 0.0);
printf("%lu\n", index);
index ++;
}
fclose(file);
return 1;
}
您正在创建一个由2个、3个或4个相同的匿名结构组成的联合,这很奇怪,但没关系,当然可以。您的函数gl_vector2_make、gl_vector3_make和gl_vector4_make,正如我第一次误读的那样,并没有返回指针,所以这也没关系。您使用realloc()的方式效率极低,但请继续。但是,您的函数
splitstring()
分配存储空间,在要处理的字符串数据中填充点,然后在返回指针之前释放分配的存储空间。这是一个严重的错误。在函数loadOBJ()
中,名为normals
、uvs
和顶点的变量都分配给固定的大小,但即使重复使用realloc()
它们,也不会增加任何变量。您总是分配相同的大小。然后根据您想要分配的大小对它们进行索引,这也是一个主要错误。此外,在loadOBJ()
中,您将整个文件读取到分配的内存中,并将其传递给splitstring()
,后者将其逐行分解为一个近似的字符串数组,然后不是实际使用该数组,而是倒带文件并使用fscanf()
再次读取整个文件,每次读取一行。为什么不在splitstring()
返回的字符串数组中的每个字符串上使用sscanf()
?好吧,联合只是为了我的利益。当我使用gl_vector4
存储颜色时,例如,使用r
、g
、b
和a
可以帮助我记住确切的用途。我想这是很公平的。那些返回局部变量指针的函数呢?啊。你没有返回指向局部变量的指针,你返回的是值,我显然误读了。嗯,完全重写了答案。再读一遍。
gl_vector3 *normals;
gl_vector2 *uvs;
gl_vector3 *vertices;
loadOBJ("/Users/justin/Downloads/OpenGL-tutorial_v0010_21/tutorial16_shadowmaps/room.obj", &vertices, &uvs, &normals);
printf("%f, %f, %f\n", vertices[0].x, vertices[0].y, vertices[0].z);