c++ - 如何使用没有运行时库的 VC++ 内部函数

标签 c++ visual-c++ intrinsics memset demoscene

我参与了您尝试生成尽可能小的二进制文件的挑战之一,因此我正在构建我的程序没有 C 或 C++ 运行时库 (RTL)。我没有链接到 DLL 版本或静态版本。我什至没有 #include 头文件。我有这个工作正常。

一些 RTL 函数,例如 memset(),可能很有用,所以我尝试添加自己的实现。它在 Debug 版本中运行良好(即使对于那些编译器生成对 memset()implicit 调用的地方)。但是在发布版本中,我收到一条错误消息,说我无法定义内在函数。你看,在 Release 版本中,内部函数被启用,并且 memset() 是一个内部函数。

我很想在我的发布版本中使用 memset() 的内在函数,因为它可能是内联的,并且比我的实现更小、更快。但我似乎是第 22 条军规中的一员。如果我没有定义 memset(),链接器会提示它未定义。如果我定义了它,编译器会提示我无法定义一个内在函数。

有谁知道定义、声明、#pragma 以及编译器和链接器标志的正确组合,以便在不增加 RTL 开销的情况下获得内在函数?

Visual Studio 2008、x86、Windows XP+。

让问题更具体一点:

extern "C" void * __cdecl memset(void *, int, size_t);

#ifdef IMPLEMENT_MEMSET
void * __cdecl memset(void *pTarget, int value, size_t cbTarget) {
    char *p = reinterpret_cast<char *>(pTarget);
    while (cbTarget > 0) {
        *p++ = static_cast<char>(value);
        --cbTarget;
    }
    return pTarget;
}
#endif

struct MyStruct {
    int foo[10];
    int bar;
};

int main() {
    MyStruct blah;
    memset(&blah, 0, sizeof(blah));
    return blah.bar;
}

我是这样构建的:

cl /c /W4 /WX /GL /Ob2 /Oi /Oy /Gs- /GF /Gy intrinsic.cpp
link /SUBSYSTEM:CONSOLE /LTCG /DEBUG /NODEFAULTLIB /ENTRY:main intrinsic.obj

如果我使用 memset() 的实现进行编译,我会收到编译器错误:

error C2169: 'memset' : intrinsic function, cannot be defined

如果我在没有实现 memset() 的情况下编译它,我会收到链接器错误:

error LNK2001: unresolved external symbol _memset

最佳答案

我想我终于找到了解决办法:

首先,在头文件中,使用 pragma 声明 memset(),如下所示:

extern "C" void * __cdecl memset(void *, int, size_t);
#pragma intrinsic(memset)

这允许您的代码调用 memset()。大多数情况下,编译器会内联内部版本。

其次,在一个单独的实现文件中,提供一个实现。防止编译器提示重新定义内部函数的技巧是首先使用另一个 pragma。像这样:

#pragma function(memset)
void * __cdecl memset(void *pTarget, int value, size_t cbTarget) {
    unsigned char *p = static_cast<unsigned char *>(pTarget);
    while (cbTarget-- > 0) {
        *p++ = static_cast<unsigned char>(value);
    }
    return pTarget;
}

这为优化器决定不使用内部版本的情况提供了一种实现。

突出的缺点是您必须禁用整个程序优化(/GL 和/LTCG)。我不确定为什么。如果有人找到一种方法可以在不禁用全局优化的情况下做到这一点,请加入。

关于c++ - 如何使用没有运行时库的 VC++ 内部函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2938966/

相关文章:

C++无法使用初始化列表初始化临时

c++ - 意外的数学除法输出 - C++

c++ - qmenu 不适用于 MAC (Qt Creator)

c++ - 快速获取 "improve"单位长度 vector 的长度

c++ - 在 OpenCV DNN 中解析来自 YOLO-Darknet 的 cfg 文件

c++ - 包装成员函数调用的模板化类的行为

基于范围的 for 循环中的 C++11 重新声明

c++ - 追踪哪个依赖项包含 SSE 指令

assembly - 与内在函数等价的 SSE2 汇编是什么?

c++ - "__rotatel4"的名称查找未找到声明