c - 修改 const char 数组引用的非常量 char 数组

标签 c constants

考虑以下代码:

struct ns_test{
    char *str;
};

struct ns_test *ns_test_alloc(char *str){
    struct ns_test *nt = malloc(sizeof(*nt));
    nt->str = str;
    return nt;
}

const char *ns_test_get_str(struct ns_test *tst){
    return tst->str;
}

void ns_test_release(struct ns_test* tst){
    free(tst);
}

void ns_test_set_char(struct ns_test *tst, size_t i, char c){
    tst->str[i] = c;
}

int main(void){
    char arr[] = "1234567890";
    struct ns_test *ns_test_ptr = ns_test_alloc(arr);
    const char *str = ns_test_get_str(ns_test_ptr);
    printf("%s\n", str); //1234567890
    ns_test_set_char(ns_test_ptr, 4, 'a');
    printf("%s\n", str); //1234a67890
}

问题是:代码的行为是否未定义?

我认为是。

标准在 6.7.3(p6) 中指定:

If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.

因此,为了避免这种 UB,我们需要 const char *ns_test_get_str(struct ns_test *tst) 来复制 char *str。但要点是避免复制并将修改限制为唯一的 void ns_test_set_char(struct ns_test *tst, size_t i, char c) 这可能会先进行一些完整性检查或其他操作。

最佳答案

这里的关键是“用 const 限定类型定义的对象”。重要的是您如何定义(IOW,“为其分配内存”)所指向的对象。如果“对象”不是作为 const“创建”的,那么无论您使用多少个 const 或非常量指针和引用都没有关系 - 您仍然可以修改它。

所以,

const int i = 0;
int *p = (int*)&i;
*p = 1;

是 UB。

同时

int i = 0;
const int *cp = &i;
int *p = (int*) cp;
*p = 1;

很好。

我怀疑这甚至可以与 new 一起使用:

const int *cp = new const int(0);
int *p = (int*) cp;
*p = 1;

在技术上是 UB。

它确实在 cpp.sh 上编译时没有警告,但这并不意味着什么。

更新:正如 Christian Gibbons 所指出的,问题中的语言是 C,因此关于 new 运算符的部分不适用。 malloc() 和 friend 永远不会是 const

稍微扩展一下 - 以这种方式编写标准的一个可能原因是让编译器可以自由地将只读内存用于 const 值。在那种情况下,写入这些位置会变成崩溃或空洞。换句话说,UB。

关于c - 修改 const char 数组引用的非常量 char 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56046844/

相关文章:

properties - D:常量正确性——我做错了什么?

c - 函数内部 static const uint8_t 更改值

c++ - 具有显式大小的可用内存

c++ - 为什么 `const` 会作用于它之前的那个东西?

javascript - 使用 const 创建动态变量

javascript - 全局常量可以在 JavaScript 中声明吗?

c - 如何读取在预期 float 末尾错误键入的字符?

c - 程序集 32 位 - 比较字符

c++ - 为什么比较 long long 和 int 会溢出

具有相同名称的 C++ const 和可变函数