Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.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++ 如何制作便携式&;编译器不可知数据?_C++_Opengl - Fatal编程技术网

C++ 如何制作便携式&;编译器不可知数据?

C++ 如何制作便携式&;编译器不可知数据?,c++,opengl,C++,Opengl,询问是否可以依靠编译器来避免混淆结构s值顺序和填充 根据对这个问题的回答, OpenGL非常清楚地定义了std140接口块的字节布局 C++11定义了一个称为的概念 C++关于布局的标准布局类型只告诉你空的基类被忽略(只要它保持标准布局),第一个NSDM将在类的最开始。也就是说,前面永远不会有填充物 该标准说的另一件事是,相同访问类的NSDM将按顺序分配,后面的NSDM的偏移量比前面的NSDM大 但是,就C++标准而言,就是这样。[class.mem]/13指出,由于各种原因,实现可以在成员之

询问是否可以依靠编译器来避免混淆
结构
s值顺序和填充

根据对这个问题的回答,

OpenGL非常清楚地定义了
std140
接口块的字节布局

C++11定义了一个称为的概念

C++关于布局的标准布局类型只告诉你空的基类被忽略(只要它保持标准布局),第一个NSDM将在类的最开始。也就是说,前面永远不会有填充物

该标准说的另一件事是,相同访问类的NSDM将按顺序分配,后面的NSDM的偏移量比前面的NSDM大

但是,就C++标准而言,就是这样。[class.mem]/13指出,由于各种原因,实现可以在成员之间添加填充

这种可能但并不总是存在的填充可能会把事情搞得一团糟,最糟糕的是——这取决于编译器


为了避免bug和噩梦,使用编译器不可知的方法不是更好吗

例如:

class BufferData
{
private:
    GLfloat data[12];

public:
    GLfloat* getCameraPosition()
    {
        return (GLfloat*) &data[0];
    }
    GLfloat* getLightPosition()
    {
        return (GLfloat*) &data[4];
    }
    GLfloat* getLightDiffuse()
    {
        return (GLfloat*) &data[8];
    }
    GLfloat* getData()
    {
        return data;
    }
};
与天真相反:

struct BufferData
{
    GLfloat camera_position[4];
    GLfloat light_position[4];
    GLfloat light_diffuse[4];
};
还是这种天真的方法足够好

(假设类/结构不止这些,而且可能会改变)

编译器不可知论“?没有这样的动物。而你试图写一本证明了这一点。考虑您的结构成员定义:

GLfloat data[12];
这需要存在
GLfloat
类型。但问题是,C++没有定义该类型。OpenGL可以

OpenGL非常清楚地定义了这个类型:它是一个

<> >,C++不要求<代码>浮点< /代码>符合此要求。事实上,C++不要求它的任何类型都符合它。如果编译器想让
float
使用IEEE-754以外的东西,那就好了

现在,您可以说OpenGL头可以将
GLfloat
定义为一个类类型,大小为32位,它将从编译器的
float
类型转换为IEEE-754。当然,那是可能发生的。。。除非无法获得32位值

有些系统有9位字节。或18位字节。这些系统有C++编译器。这样的系统不能声明一个只有32位大小的类型

但是能够传递32位的值(更不用说16位和8位)是OpenGL的一个硬要求。如果没有缓冲区,您将无法在缓冲区对象中传递任何数据。然而,C++不需要它。 说到顶点数据,半现代OpenGL中最基本的函数之一是
glVertexAttributePointer
。它依赖于您将一个字节偏移量强制转换为一个
void*
,然后将其强制转换回

C++不能保证这是可行的。C++标准中没有任何地方需要,如果将一个整数转换为指针,然后将该指针重新映射为整数,则返回相同的整数(它确实表示PTR>INT>PTR工作,但这并不意味着相反)。 然而OpenGL需要它。除非使用单独的属性缓冲区(and),否则代码和调用的OpenGL代码依赖于此未定义的行为

OpenGL将GLint定义为一个有符号的、2的补码、32位整数。但是C++不需要任何整数类型为两个补码。 但OpenGL确实如此

OpenGL flat out无法在具有异常大小的类型的系统上运行。它不能在具有9位字节的系统上运行。它不能在使用有符号整数数学的补码的系统上运行。我可以继续这样说,但我想我的观点是明确的

通过选择使用OpenGL(如果您想知道的话,也可以使用Vulkan),您已经依赖于实现定义的行为。那么,既然您已经依赖于大量其他实现定义的行为,为什么还要费心让您的生活更加难以避免这种特定的实现定义行为呢


马已经出了马厩;现在关上门也没用。

我真的可以学究一点,建议应该是
GLfloat
而不是
float
@G.M。是的,你可以。这是一个关于学究的问题。我正在编辑..除非你支持很多编译器,否则你可能只需要评估它是否适用于你使用的少数编译器,并就此结束。如果你正在处理一个库,而该库可能由任何编译器上的任何人编译呢?@IvanRubinson指定一个受支持的编译器列表。IIRC这就是GLM对其联合类型所做的。好的。只要类型的大小不是异常的(是2的幂吗)?@IvanRubinson:那么我假设你将停止使用
glvertexattributepointer
和任何类似的函数,假装指针是字节偏移量,那么编译器不可知的解决方案呢?我的观点是,您已经依赖于大量其他实现定义的行为。为什么在结构布局上“编译器不可知”如此重要?类型的布局通常是最容易检查的(因为它通常由平台ABI定义)。“指针是字节偏移量”在C语言中编程时不是一件正常的事情吗?@IvanRubinson:“指针是字节偏移量”在C语言中编程时不是一件正常的事情吗?”我不是C语言编程专家,但不,它不是。我认为除了OpenGL,我从来没有见过真正需要将整数转换成指针,然后将其传递给将其转换回整数的人的C API。现在,我确实知道一些C API依赖于将指针转换为整数并返回,但这实际上是由标准保证的(只要整数类型足够大)。