放弃函数参数的常量是否是未定义行为?

发布于 2025-01-01 17:19:56 字数 324 浏览 6 评论 0原文

想象一下,我有这个 C 函数(以及头文件中的相应原型),

void clearstring(const char *data) {
    char *dst = (char *)data;
    *dst = 0;
}

上面的代码中是否存在未定义的行为,const 转换掉,或者只是一个可怕的行为不好的编程习惯?

假设没有使用 const 限定的对象

char name[] = "pmg";
clearstring(name);

Imagine I have this C function (and the corresponding prototype in a header file)

void clearstring(const char *data) {
    char *dst = (char *)data;
    *dst = 0;
}

Is there Undefined Behaviour in the above code, casting the const away, or is it just a terribly bad programming practice?

Suppose there are no const-qualified objects used

char name[] = "pmg";
clearstring(name);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧瑾黎汐 2025-01-08 17:19:56

如果调用者向您传递一个指向 const 对象的指针或指向字符串文字的指针,则尝试写入 *dst 是 UB

但是,如果调用者向您传递一个指向实际上可变的数据的指针,则行为就被定义了。创建指向可修改 charconst char* 并不会使该 char 不可变。

所以:

char c;
clearstring(&c);    // OK, sets c to 0
char *p = malloc(100);
if (p) {
    clearstring(p); // OK, p now points to an empty string
    free(p);
}
const char d = 0;
clearstring(&d);    // UB
clearstring("foo"); // UB

也就是说,你的函数是非常不明智的,因为调用者很容易导致UB。但实际上可以将其用于定义的行为。

The attempt to write to *dst is UB if the caller passes you a pointer to a const object, or a pointer to a string literal.

But if the caller passes you a pointer to data that in fact is mutable, then behavior is defined. Creating a const char* that points to a modifiable char doesn't make that char immutable.

So:

char c;
clearstring(&c);    // OK, sets c to 0
char *p = malloc(100);
if (p) {
    clearstring(p); // OK, p now points to an empty string
    free(p);
}
const char d = 0;
clearstring(&d);    // UB
clearstring("foo"); // UB

That is, your function is extremely ill-advised, because it is so easy for a caller to cause UB. But it is in fact possible to use it with defined behavior.

ˇ宁静的妩媚 2025-01-08 17:19:56

考虑像 strstr 这样的函数,如果给定一个指向包含字符串的对象的一部分的指针,则返回一个指向同一对象的可能不同部分的指针。如果该方法传递一个指向只读内存区域的指针,它将返回一个指向只读内存区域的指针;同样,如果给它一个指向可写区域的指针,它将返回一个指向可写区域的指针。

在 C 中,无法让函数在给定 const char * 时返回 const char *,并在给定 const char * 时返回普通 char *给定一个普通的char *。为了与 strstr 在 const char * 的概念被添加到该语言之前的工作方式兼容,它必须将 const 限定的指针转换为非 const 限定的指针。 -const 限定指针。虽然作为库函数 strstr 确实可能有权执行此类转换,即使用户代码不能,但相同的模式在用户代码中经常出现,因此禁止它是可行的。

Consider a function like strstr which, if given a pointer to a part of an object containing a string, with return a pointer to a possibly-different part of the same object. If the method is passed a pointer to a read-only area of memory, it will return a pointer to a read-only area of memory; likewise if it is given a pointer to a writable area, it will return a pointer to a writable area.

There is no way in C to have a function return a const char * when given a const char *, and return an ordinary char * when given an ordinary char *. In order to be compatible with the way strstr worked before the idea of a const char * was added to the language, it has to convert a const-qualified pointer into a non-const-qualified pointer. While it's true that as a library function strstr might be entitled to do such a cast even if user code could not, the same pattern comes up often enough in user code that it would be practical to forbid it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文