c - 使用 `const` 中断程序

标签 c opengl constants

我使用 SDL 2.0 和 OpenGL 1.1 编写了一个小测试程序,并遇到了这个非常奇怪的问题:使某些变量 const 破坏了程序!谁能解释一下为什么会发生这种情况?

代码

static float vertexes[] = { // Good
static uint8_t colors[] = {

static float vertexes[] = { // No problem
static const uint8_t colors[] = {

static const float vertexes[] = { // Bad
static const uint8_t colors[] = {

static const float vertexes[] = { // VERY bad
static uint8_t colors[] = {

各自的截图

Screen when neither are constant Screen when <code>colors</code> is constant Screen when <code>vertexes</code> is constant Screen when both are constant

完整(工作)程序

该程序给出了所需的行为。注释掉 const 以查看损坏的版本。

// gcc -o main main.c -std=c11 -pedantic -Wall -I. -lm -lmingw32 -lSDL2main -lSDL2 -lopengl32 -lglu32 -mwindows
#include <SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(*arr))

typedef struct {
    float x;
    float y;
    float z;
} vec3;

bool running;
int width, height;
SDL_Window *window;
SDL_GLContext ctx;
vec3 rotation;

static /* const */ float vertexes[] = {
     1.0f,  1.0f,  1.0f,
     1.0f, -1.0f, -1.0f,
     1.0f,  1.0f, -1.0f,
     1.0f, -1.0f, -1.0f,
     1.0f,  1.0f,  1.0f,
     1.0f, -1.0f,  1.0f,

    -1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,
    -1.0f, -1.0f, -1.0f,
    -1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f, -1.0f,

     1.0f, -1.0f,  1.0f,
    -1.0f, -1.0f, -1.0f,
     1.0f, -1.0f, -1.0f,
     1.0f, -1.0f,  1.0f,
    -1.0f, -1.0f,  1.0f,
    -1.0f, -1.0f, -1.0f,

     1.0f,  1.0f,  1.0f,
     1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,
     1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f,  1.0f,

     1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,
     1.0f, -1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,
    -1.0f, -1.0f,  1.0f,
     1.0f, -1.0f,  1.0f,

     1.0f,  1.0f, -1.0f,
    -1.0f, -1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,
     1.0f,  1.0f, -1.0f,
     1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f, -1.0f,
};
static /* const */ uint8_t colors[] = {
    0x00, 0x00, 0xFF,
    0x00, 0x00, 0xFF,
    0x00, 0x00, 0xFF,
    0x00, 0x00, 0xFF,
    0x00, 0x00, 0xFF,
    0x00, 0x00, 0xFF,

    0x00, 0x7F, 0x3F,
    0x00, 0x7F, 0x3F,
    0x00, 0x7F, 0x3F,
    0x00, 0x7F, 0x3F,
    0x00, 0x7F, 0x3F,
    0x00, 0x7F, 0x3F,

    0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF,

    0xFF, 0xFF, 0x00,
    0xFF, 0xFF, 0x00,
    0xFF, 0xFF, 0x00,
    0xFF, 0xFF, 0x00,
    0xFF, 0xFF, 0x00,
    0xFF, 0xFF, 0x00,

    0xFF, 0xB3, 0x00,
    0xFF, 0xB3, 0x00,
    0xFF, 0xB3, 0x00,
    0xFF, 0xB3, 0x00,
    0xFF, 0xB3, 0x00,
    0xFF, 0xB3, 0x00,

    0xFF, 0x00, 0x00,
    0xFF, 0x00, 0x00,
    0xFF, 0x00, 0x00,
    0xFF, 0x00, 0x00,
    0xFF, 0x00, 0x00,
    0xFF, 0x00, 0x00,
};

void onresize(void)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60, (float)width/(float)height, 1, -1);
}

void init(void);
void fini(void);

void loop(void);

void handle(void);
void render(void);
void update(void);

int main(int argc, char* argv[])
{
    init();
    loop();
    fini();

    return 0;
}

void init(void)
{
    SDL_DisplayMode mode;

    if (SDL_Init(SDL_INIT_VIDEO)) return;

    SDL_GetDesktopDisplayMode(0, &mode);
    width = mode.w;
    height = mode.h;
    window = SDL_CreateWindow(
        "Game",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        width,
        height,
        SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN
    );
    if (!window) return;
    ctx = SDL_GL_CreateContext(window);
    if (!ctx) return;

    onresize();
    glEnable(GL_DEPTH_TEST);

    running = true;
}
void fini(void)
{
    if (ctx) SDL_GL_DeleteContext(ctx);
    if (window) SDL_DestroyWindow(window);

    SDL_Quit();
}

void loop(void)
{
    while (running) {
        handle();
        render();
        update();
    }
}

void handle(void)
{
    SDL_Event event;

    while (SDL_PollEvent(&event)) {
        switch (event.type) {
        case SDL_WINDOWEVENT:
            switch (event.window.event) {
            case SDL_WINDOWEVENT_RESIZED:
                width = event.window.data1, height = event.window.data2;
                onresize();

                break;
            }
            break;
        case SDL_QUIT:
            running = false;
            break;
        default:
            break;
        }
    }
}
void render(void)
{
    glClearColor(0.9f, 0.8f, 0.7f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 0, -5, 0, 0, 0, 0, 1, 0);
    glRotatef(rotation.x, 1, 0, 0);
    glRotatef(rotation.y, 0, 1, 0);
    glRotatef(rotation.z, 0, 0, 1);
    glScalef(0.25f, 0.25f, 0.25f);

    glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
    glBegin(GL_LINES);
        glVertex3f(0.0f, 0.0f, 0.0f);
        glVertex3f(9.0f, 0.0f, 0.0f);
        glVertex3f(0.0f, 0.0f, 0.0f);
        glVertex3f(0.0f, 9.0f, 0.0f);
        glVertex3f(0.0f, 0.0f, 0.0f);
        glVertex3f(0.0f, 0.0f, 9.0f);
    glEnd();

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

        glVertexPointer(3, GL_FLOAT, 0, vertexes);
        glColorPointer(3, GL_UNSIGNED_BYTE, 0, colors);
        glDrawArrays(GL_TRIANGLES, 0, ARRAYSIZE(vertexes));

    glEnableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

    SDL_GL_SwapWindow(window);
}
void update(void)
{
    rotation.x++;
    rotation.y++;
}

可选 here .

最佳答案

glDrawArrays() 调用中使用 ARRAYSIZE(vertexes)/3 而不是 ARRAYSIZE(vertexes)

glDrawArrays()count 参数是顶点数,而不是 float 。现在,您告诉 OpenGL 将顶点/颜色数组的末尾读入 $DIETY-knows-what。你很幸运,它没有出现段错误。

const/non-const 可能只是 switching其中segment数组最终会为 OpenGL 提供不同的“垃圾”顶点来尝试解释。

关于c - 使用 `const` 中断程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38402726/

相关文章:

c - printf() 函数中的参数列表是什么?

c - 客户端服务器实现的命名管道-服务器如何区分来自同一客户端的两个请求

c++ - 带有 tinyobjloader 的 OpenGL 顶点数组对象

c++ - 在 openGL 中绘制平面

cocoa - Mac 上全屏 OpenGL 的问题

c - 了解 C 中 const buffer 和 read() 的使用

c - GCC vs CLANG 指向 char* 优化的指针

c - 为什么地址编号在十进制和十六进制中不相等?

c++ - 在头文件中声明和初始化常量

c++ - 创建指向 "this"对象的指针