编辑: 我做了一些假设,例如静态变量将在运行时第一次调用函数时创建并初始化。
我现在知道情况并非如此,现在只需定义一个静态并返回它的指针,并在程序开始时调用一次init函数,因此基本上与我在执行时的操作相同使用全局变量但保持全局范围。
原件:
我正在尝试避免通常建议的全局变量,但需要一些我可以在多个函数中引用的静态数据,而不必经常将对象传递给每个函数(尽管如果这最终不起作用我可能不得不诉诸于那个)
另一个潜在的优势是因为我使用它的大部分功能都经常被调用,只对初始化一次的数据应该永远不会改变应该最小化性能损失。
我提出的方法是创建一个静态变量并启动它一次,如果我需要在单个函数中使用它我会直接在函数内初始化然后使用它,如果我需要多个函数我将在一个单独的静态函数中启动它,其他人可以调用指针
编辑: WINDOWS是一个自定义宏
#ifndef WINDOWS
#if defined(_WIN32) || defined(_WIN64)
#define WINDOWS
#endif
#endif
编译器也是MinGW 64bit
示例A编译很好但是示例B引发错误“初始化元素不是常量”
示例A:
static ProgramPath getPath() {
ProgramPath result;
// Get Executable Path
#ifdef WINDOWS
GetModuleFileName(NULL, result.executablePath, sizeof(result.executablePath));
#endif
// Seperate Path and Executable into Seperate Variables
for (unsigned int i = 0; i < sizeof result.executablePath; ++i) {
// Convert \ to /
if (result.executablePath[i] == 0x5c) {
result.executablePath[i] = 0x2F;
} else if (result.executablePath[i] == 0x0) { // 0x0 means we've reached end of string.
unsigned int j;
// Get Executable Name Sub String
for (j = i - 1; j > 0; --j) {
if (result.executablePath[j] == 0x2F) { // Stop when we reach a /
result.executableStringLen = i - j;
memcpy(&result.executable, &result.executablePath[j + 1], result.executableStringLen); // Copy Executable SubString into correct variable
break;
}
}
result.executableStringLen = ++j;
// Remove Executable from Path
for (; j < i; ++j) {
result.executablePath[j] = 0x0;
}
break;
}
}
CA_VERBOSE_DEBUG("Executable: %s", executable);
CA_PRINT_DEBUG("Executable Path: %s", executablePath);
return result;
}
static inline ProgramPath *getPathInfo() {
static ProgramPath programPath = getPath();
return &programPath;
}
例B:
static GraphicsInfo getGraphicsInfo() {
GraphicsInfo result;
result.internalPixelFormat = GL_BGRA;
result.internalPixelType = GL_UNSIGNED_INT_8_8_8_8_REV;
// Get Preferred Internal Pixel Format
if (glGetInternalformativ) {
const GLenum preferedInternalFormats[4] = {
GL_RGB,
GL_BGR,
GL_RGBA,
GL_BGRA
};
GLint test;
// Check for Internally Supported Formats and Use Best One
for (int i = 3; i >= 0; --i) {
// Check for Prefered
glGetInternalformativ(GL_RENDERBUFFER, preferedInternalFormats[i], GL_INTERNALFORMAT_PREFERRED, 1, &test);
if (test == GL_TRUE) {
result.internalPixelFormat = preferedInternalFormats[i];
break;
}
}
}
return result;
}
static inline GraphicsInfo *CA_getGraphicsInfo() {
static GraphicsInfo result = getGraphicsInfo(); // Error Occurs Here
return &result;
}
我也试过评论示例B中的大部分代码都无济于事
答案 0 :(得分:1)
您无法从函数的返回值初始化具有static
存储的变量:
static inline GraphicsInfo *CA_getGraphicsInfo() {
static GraphicsInfo result = getGraphicsInfo(); // Error Occurs Here
return &result;
}
2个代码片段处理您未提供定义的不同结构,也不应编译,但请注意,如果未定义WINDOWS
,getPath
将操作未初始化的结构{{1}所以任何事情都可能发生,包括编译器在你身上耍花招。
由于两个函数都定义为result
,因此编译器也可能仅在实际尝试在呼叫站点内联展开static inline
时报告错误,并且仍然报告错误内联函数定义的位置。
此外,以下是getPath
:
它会在可能重叠的对象上调用getPath
,这也会调用未定义的行为:改为使用memcpy
。
memmove
不正确,应予以删除。如果找到result.executableStringLen = ++j;
,则已更新长度,但您应在搜索到'/'
之前对其进行初始化
如果找不到result.executableStringLen = i;
,则除了第一个字节外,有效清除数组。您应该从'/'
。