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

使用consteval实现C++字符串加密时遭遇编译错误求助

问题:consteval字符串加密编译错误原因及解决方法

背景

原本用constexpr实现字符串加密,但部分字符串会在运行时执行,换成consteval强制编译时执行后,出现编译错误。

核心错误提示

Call to consteval function 'encrypt_string' is not a constant expression
pointer to subobject of temporary is not a constant expression

宏展开后的代码

decrypt_string(encrypt_string((char[]) { "s/x/apkpath/MainActivity" }, sizeof(char[])
    { "s/x/apkpath/MainActivity" }),sizeof(char[])
    { "s/x/apkpath/MainActivity" })

函数实现

consteval auto encrypt_string(char string[], uint32_t len) {
    for (int i = 0; i != len; i++) {
        string[i] = string[i] ^ keys_expr[i & 7];
    }
    return string;
}

__attribute__((visibility("hidden"))) __attribute__((noinline)) __attribute__((optnone))
auto decrypt_string(char string[], int len) {
    for (int i = 0; i != len; i++) {
        string[i] = (string[i] & ~keys[i & 7]) | (~(string[i] & keys[i & 7]) & keys[i & 7]);
        //string[i] = string[i] ^ keys[i & 7];
    }
    return string;
}

编译配置(Android Studio + Clang)

在build.gradle中添加:

externalNativeBuild {
    cmake {
        cppFlags '-std=c++20'
    }
}

完整编译错误信息

C:\Users\*\AppData\Local\Android\Sdk\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android24 --sysroot=C:/Users/*/AppData/Local/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/windows-x86_64/sysroot -Dapkpath_EXPORTS  -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security  -std=c++20 -fno-limit-debug-info  -fPIC -MD -MT CMakeFiles/apkpath.dir/apkpath.cpp.o -MF CMakeFiles\apkpath.dir\apkpath.cpp.o.d -o CMakeFiles/apkpath.dir/apkpath.cpp.o -c C:/Users/*/AndroidStudioProjects/ApkPath/app/src/main/cpp/apkpath.cpp

C:/Users/*/AndroidStudioProjects/ApkPath/app/src/main/cpp/apkpath.cpp:15:17: error: call to consteval function 'encrypt_string' is not a constant expression
        decrypt_string(encrypt_string((char[]) { "s/x/apkpath/MainActivity" }, sizeof(char[])
                       ^
C:/Users/*/AndroidStudioProjects/ApkPath/app/src/main/cpp/apkpath.cpp:15:17: note: pointer to subobject of temporary is not a constant expression
C:/Users/*/AndroidStudioProjects/ApkPath/app/src/main/cpp/apkpath.cpp:15:32: note: temporary created here
        decrypt_string(encrypt_string((char[]) { "s/x/apkpath/MainActivity" }, sizeof(char[])
                                      ^

错误原因

  1. 临时对象指针不符合常量表达式规则:consteval要求所有操作必须是编译期可计算的常量表达式。你传入的(char[]) { "s/x/apkpath/MainActivity" }是临时数组,指向它的指针无法作为常量表达式——编译期无法确定临时对象的稳定地址。
  2. 字符串字面量的const属性冲突:字符串字面量本质是const char[],强制转为char[]试图修改的操作,在consteval的常量表达式上下文中不被允许。

解决方法

方案1:编译期生成加密数组(推荐)

修改encrypt_string返回编译期加密后的数组,完全避免临时指针问题:

// 提前定义编译期密钥(必须是constexpr数组)
constexpr uint8_t keys_expr[8] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};

template<size_t N>
consteval auto encrypt_string(const char (&str)[N]) {
    std::array<char, N> result{};
    for (size_t i = 0; i < N; ++i) {
        result[i] = str[i] ^ keys_expr[i & 7];
    }
    return result;
}

// 解密函数简化(原写法等价于异或)
__attribute__((visibility("hidden"))) __attribute__((noinline)) __attribute__((optnone))
const char* decrypt_string(char string[], int len) {
    for (int i = 0; i != len; ++i) {
        string[i] ^= keys[i & 7];
    }
    return string;
}

// 宏简化写法
#define ENCRYPTED_STR(str) \
    []() { \
        auto encrypted_arr = encrypt_string(str); \
        return decrypt_string(encrypted_arr.data(), encrypted_arr.size()); \
    }()

encrypt_string在编译期生成加密后的std::array,运行时调用解密函数即可,完全符合consteval的编译期执行要求。

方案2:静态存储数组结合constexpr

如果坚持修改传入数组,需将字符串放在静态存储区,但consteval无法修改静态变量,因此改回constexpr并通过static_assert强制编译期执行:

constexpr auto encrypt_string(char string[], uint32_t len) {
    for (int i = 0; i != len; i++) {
        string[i] = string[i] ^ keys_expr[i & 7];
    }
    return string;
}

// 宏写法
#define ENCRYPTED_STR(str) \
    []() { \
        static char arr[] = str; \
        static_assert(encrypt_string(arr, sizeof(arr)) != nullptr, "Compile-time encryption failed"); \
        return decrypt_string(arr, sizeof(arr)); \
    }()

关键注意事项

  • consteval函数的所有操作必须是纯编译期的,不能涉及运行时对象(如临时指针、静态变量修改)。
  • 字符串字面量是const的,不能直接在常量表达式中修改,必须复制到可修改的编译期数组中。
  • 解密函数必须在运行时执行,需将编译期生成的加密数组传递给它,而非直接返回编译期指针。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:54:53