想象我有这个C函数(在头文件中的相应的原型)它是未定义行为来抛弃函数参数的常量吗?
void clearstring(const char *data) {
char *dst = (char *)data;
*dst = 0;
}
有没有在上面的代码中未定义行为,铸造const
走,或者是它只是一个非常不好的编程习惯?
假设有没有const限定对象使用
char name[] = "pmg";
clearstring(name);
想象我有这个C函数(在头文件中的相应的原型)它是未定义行为来抛弃函数参数的常量吗?
void clearstring(const char *data) {
char *dst = (char *)data;
*dst = 0;
}
有没有在上面的代码中未定义行为,铸造const
走,或者是它只是一个非常不好的编程习惯?
假设有没有const限定对象使用
char name[] = "pmg";
clearstring(name);
的尝试写入*dst
是UB 如果调用者传递你指向一个const对象,或指向一个字符串。
但是,如果调用者向您传递指向实际上可变的数据的指针,则会定义行为。创建指向可修改的const char*
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。但实际上可以将其与定义的行为一起使用。
考虑一个函数,如strstr
,如果给定一个指向包含字符串的对象的一部分的指针,并返回一个指向同一对象的可能不同部分的指针。如果该方法传递一个指向内存只读区域的指针,它将返回一个指向内存只读区域的指针;同样,如果给它一个指向可写区域的指针,它将返回一个指向可写区域的指针。
当给定const char *
时,C无法让函数返回const char *
,并且在给定普通char *
时返回普通char *
。为了兼容strstr
在将const char *
的想法添加到语言之前工作,必须将const限定指针转换为非const限定指针。尽管确实如此,即使用户代码不能,库函数strstr
也许有权做这样的投射,但在用户代码中经常出现相同的模式,以至于禁止它是实际的。
如果演员阵容不是UB,我认为它应该是:) – pmg 2012-01-31 11:55:28
你当然有你的脚在霰弹枪的景点! – 2012-01-31 11:57:56
@pmg:如果转换本身是UB,那么语言允许的话就没有什么意义了 - 编译器很容易检测到const已经被添加到了转换中,就像它检测到'char * dst = data;'是非法的。显然有一些没有意义的事情是由于历史原因标准允许的,但我声称这不是其中之一:-) – 2012-01-31 12:08:30