【问题标题】:Check if string can be mutated in C检查字符串是否可以在C中变异
【发布时间】:2015-02-07 00:56:44
【问题描述】:

假设我有这个功能:

void f(char *s) {
    s[0] = 'x';
}

此功能有时会导致错误,有时不会。例如,

char *s = "test";
f(s); // Error

char t[] = "test";
f(t); // Success

f函数内部,是否可以先判断s[0] = 'x';会不会出错?

【问题讨论】:

  • 我不相信有任何便携的方法可以做到这一点。不过,可能会有一些特定于平台的技术。
  • 如果有人选择以表现出未定义行为的方式使用您的函数,并且您的函数有据可查,那就是他们。
  • 尝试修改 const 对象会导致未定义的行为。实际上,这意味着你不能编写一个测试这个的函数。但是,您可以通过严格指定哪些对象是 const 来获得编译时诊断,因此您永远不会尝试修改它们或将 const 对象传递给修改它的函数。
  • @EOF:字符串文字不是const 对象。但是由于特殊情况规则,修改字符串文字仍然具有未定义的行为。
  • @KeithThompson:是的。它实际上具有const 语义。

标签: c arrays string constants


【解决方案1】:

调用者有责任遵守函数的要求,即参数是可变的,而不是相反。

const char *s = "test";     //  tell compiler s is immutable
f(s);                       //  compilation error since f() requires a non-const argument

char t[] = "test";
f(t); // Success

在上面阻止编译器拒绝 f(s) 的唯一方法是从 s 的声明中删除 const,或者将 const'ness 去掉。除了极少数情况外,两者都是问题的积极指标。

注意:在没有 const 限定符的情况下可以声明 s 是一种语言异常。练习在需要的地方使用 const(例如,在使用字符串字面量初始化指针时)。这样就消除了很多程序错误。

【讨论】:

    【解决方案2】:

    鉴于我收到的反馈,听起来我应该记录该函数是否要求其参数是可变的。例如:

    #include <stdio.h>
    #include <string.h>
    
    char* f(char*);
    void g(char*);
    
    int main(int argc, char *argv[]) {
        // s is immutable.
        char *s = "test";
        puts(f(s));
    
        // t is mutable.
        char t[] = "test";
        g(t);
        puts(t);
    }
    
    /*
     * Returns a copy of the given string where the first character is replaced with 'x'.
     * Parameter s must contain at least one character.
     */
    char* f(char *s) {
        char *t = strdup(s);
        t[0] = 'x';
        return t;
    }
    
    /*
     * Replaces the first character of the given sting with 'x'.
     * Parameter s must contain at least one character and be mutable.
     */
    void g(char *s) {
        s[0] = 'x';
    }
    

    【讨论】:

    • "...记录函数是否要求其参数是可变的..." 这不就是 const 的发明目的吗?
    • @c-smile 在这个例子中,函数g 要求参数s 是非常量的。在这方面有没有办法使用const?如果是这样,请发布答案,我会接受。
    • 您的函数g() 修改传递给它的字符串这一事实是您需要的所有文档,在这里。
    • 使用 strdup() 会导致内存泄漏,因此不是完全可行的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    相关资源
    最近更新 更多