You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C++ constexpr函数返回编译期常量字符串字面量

编译期从__FILE__提取独立文件名(MSVC下实现)

可行,但原实现无法达成目标,核心原因是:你的函数返回的是__FILE__原字符串字面量的子串指针,编译器不会自动将该子串单独提取为新的字符串字面量,因此完整路径仍会保留在二进制中。要实现仅保留文件名的目标,需通过编译期构造独立字符数组的方式生成文件名。

问题分析

__FILE__是编译器注入的完整路径字符串字面量,原函数返回的指针指向该字面量的某一位置。即使编译器在编译期计算出了指针位置,也不会主动将子串剥离为独立字面量——因为指针依赖原字符串的存在,所以完整路径会被保留,无法达到你想要的效果。

解决方案:编译期构造独立文件名数组

通过constexpr构造一个仅包含文件名的字符数组,编译器会在编译期直接生成该数组的常量数据,原__FILE__的完整路径会因未被实际引用而被优化移除(需配合MSVC的优化设置)。

示例代码(兼容跨平台)

#include <iostream>

constexpr auto get_filename() {
    // 定位文件名起始位置
    const char* file = __FILE__;
    const char* name_start = file;
    while (*file != '\0') {
        if (*file == '\\' || *file == '/') {
            name_start = file + 1;
        }
        ++file;
    }

    // 编译期计算文件名长度
    constexpr size_t name_len = []{
        const char* f = __FILE__;
        const char* s = f;
        while (*f != '\0') {
            if (*f == '\\' || *f == '/') {
                s = f + 1;
            }
            ++f;
        }
        return static_cast<size_t>(f - s);
    }();

    // 编译期构造文件名数组
    char filename[name_len + 1]{};
    for (size_t i = 0; i < name_len; ++i) {
        filename[i] = name_start[i];
    }
    filename[name_len] = '\0';

    return filename;
}

int main() {
    std::cout << get_filename() << std::endl;
    return 0;
}

MSVC优化配置要求

确保以下设置生效:

  • 开启最高优化级别:/O2(Release模式默认开启)
  • 启用引用优化:/OPT:REF(默认开启,会移除未被引用的全局数据,包括原__FILE__完整路径)
  • 关闭"保留未使用的符号"相关选项,避免原字符串被保留

说明

  • 代码同时处理Windows的\\路径分隔符和类Unix的/分隔符,具备跨平台兼容性。
  • 编译期构造的字符数组会直接嵌入二进制,仅包含文件名内容,原完整路径不会出现在最终可执行文件中。

内容的提问来源于stack exchange,提问作者Arush Agarampur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 18:10:30