2012-01-31 24 views
13

想象我有这个C函数(在头文件中的相应的原型)它是未定义行为来抛弃函数参数的常量吗?

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

有没有在上面的代码中未定义行为,铸造const,或者是它只是一个非常不好的编程习惯?

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

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

如果演员阵容不是UB,我认为它应该是:) – pmg 2012-01-31 11:55:28

+0

你当然有你的脚在霰弹枪的景点! – 2012-01-31 11:57:56

+1

@pmg:如果转换本身是UB,那么语言允许的话就没有什么意义了 - 编译器很容易检测到const已经被添加到了转换中,就像它检测到'char * dst = data;'是非法的。显然有一些没有意义的事情是由于历史原因标准允许的,但我声称这不是其中之一:-) – 2012-01-31 12:08:30

回答

20

的尝试写入*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。但实际上可以将其与定义的行为一起使用。

+4

+1:(im)可变性是对象本身的固有属性,无论是否具有用于访问它的指针... – Christoph 2012-01-31 12:01:58

+0

因为“C99 6.6§9”还是因为“C99 6.7.3§5”,这是UB吗? – Lundin 2012-01-31 14:13:43

+1

@Lundin:后者(在字符串的情况下,6.4.5/6而不是6.7.3/5,因为字符串文本不是C中的'const'对象)。地址常量与此无关。 – 2012-01-31 14:24:55

0

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

当给定const char *时,C无法让函数返回const char *,并且在给定普通char *时返回普通char *。为了兼容strstr在将const char *的想法添加到语言之前工作,必须将const限定指针转换为非const限定指针。尽管确实如此,即使用户代码不能,库函数strstr也许有权做这样的投射,但在用户代码中经常出现相同的模式,以至于禁止它是实际的。

相关问题