为什么程序员在OpenGL中使用常量和静态变量?

4
我注意到程序员会将变量设为 conststatic。我知道这些关键字的作用,但不知道他们为什么使用它们。

示例1
取自The Official Guide to Learning OpenGL, Version 1.1第2章

    static GLint vertices[] = {25, 25,
                              100, 325,
                              175, 25,
                              175, 325,
                              250, 25,
                              325, 325};

    static GLfloat colors[] = {1.0, 0.2, 0.2,
                              0.2, 0.2, 1.0,
                              0.8, 1.0, 0.2,
                              0.75, 0.75, 0.75,
                              0.35, 0.35, 0.35,
                              0.5, 0.5, 0.5};

    glEnableClientState (GL_COLOR_ARRAY);
    glEnableClientState (GL_VERTEX_ARRAY);

    glColorPointer (3, GL_FLOAT, 0, colors);
    glVertexPointer (2, GL_INT, 0, vertices);

如果这些数组只在单个对象实例中使用,为什么它们必须是静态的?


示例2
来自wikibooks上的OpenGL编程教程1

    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);

    const char *fs_source =
    "#version 120           \n"
    "void main(void) {        "
    "  gl_FragColor[0] = 0.0; "
    "  gl_FragColor[1] = 0.0; "
    "  gl_FragColor[2] = 1.0; "
    "}";

    glShaderSource(fs, 1, &fs_source, NULL);

在设置后,fs_source字符数组不会被更改。但是将其设置为常量绝对必要吗?这会提高性能吗?

3个回答

4
通常来说,它确实可以提高性能,但不一定是你想象的那种方式。有了这些提示,编译器可以自由选择不同的优化(包括空间和时间),从而使代码更加高效。例如,静态存储期变量(a)在程序启动时初始化一次,以后就不需要再初始化了。将某些内容标记为“const”可以让编译器生成更有效的代码,因为数据不会被改变。极端情况下,它可以将值加载到专用CPU寄存器中,并永远不再查看内存中的数据。因此,它确实可以提高性能,但不是因为相同的指令在底层运行得更快,而是因为编译器可以根据你给出的额外信息使用不同的指令。注意:(a):假设这是您对“static”的意思。还有几个关键字用于限制其可见性范围,这是良好的编程实践。

如果你以一个uniform为基础创建一个静态常量,它是否仍然只会被计算一次而不是每个顶点和片段都要计算? - jjxtra

4

我明白这些关键字的作用,

你呢?

但是我不知道他们为什么使用它们。

你呢?!

如果这些数组只在单个对象实例中使用,为什么它们必须是静态的?

什么对象?什么实例?你引用的书例子是用C语言写的,而不是C++。虽然在C语言中完全有可能使用对象和实例的概念,但语言本身没有内置这些定义。因此,在这种情况下,你对于static的理解是错误的。

在给定的例子中,如果在模块级别上应用static,将其应用到全局变量上。这样做的效果是,该变量仅对其定义所在的编译单元可见。在C程序中,被推荐的常见做法是声明所有不需要在当前编译单元之外引用的变量为static

在函数范围内使用静态常量数据可以避免每次调用函数时都进行变量的完整初始化,从而提高效率。

设置之后,fs_source字符数组不会被修改。

实际上你也无法修改。C语言规定,不是char数组初始化的字符串字面量是const char *类型,并且驻留在程序映像的一个专用只读段中。由于非初始化器字符串字面量的类型是const char *,将这样的指针变量分配给char *会导致未定义行为。

但是把它设为常量绝对必要吗?

试试移除const并使用-Werr编译程序,看看会发生什么。这实际上是语言正确性的问题。


1
在我们讨论的文件varray.c(示例1)中:
示例中的静态变量未在模块级别声明,其可见性仅限于函数内部。static关键字在不同情况下可能意味着不同的含义,但在这种情况下,它并不是为了限制其他代码文件对其可访问性的限制(但通过将其作用域限制为函数,这一点已经实现了)。
这些数组仅在程序运行期间声明/生成一次。在这些声明前面添加static关键字(例如在setupPointers中)意味着这些代码行(59-64、65-70)仅执行一次,并且指针本身不会更改,这些数字也不必再次“流过管道”(有关性能的答案请参见上文),因为它们已经存在。
这是因为当用户单击鼠标按钮时,程序在两个绘图例程之间切换。只初始化数组一次而不是每次调用setupPointers函数是有意义的。
所以,这就是static关键字起作用的一种方式,它告诉编译器仅初始化此变量一次。const类似,但它的含义更像是“仅写入此内存一次”。

你可能会说,那为什么不把它们设为常量呢?我知道,对吧?

也许这些链接可以帮助人们:

varray.c

关于静态关键字的博客文章


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接