【问题标题】:String in function parameter函数参数中的字符串
【发布时间】:2013-06-11 06:13:42
【问题描述】:
int main()
{
        char *x = "HelloWorld";
        char y[] = "HelloWorld";

        x[0] = 'Z';
        //y[0] = 'M';

        return 0;
}

在上述程序中,HelloWorld 将位于只读部分(即字符串表)。 x 将指向该只读部分,因此尝试修改该值将是未定义的行为。

y 将在堆栈中分配,HelloWorld 将被复制到该内存中。所以修改 y 可以正常工作。 String literals: pointer vs. char array

这是我的问题:

在下面的程序中,char *arrchar arr[] 如果内容被修改,都会导致分段错误。

void function(char arr[])
//void function(char *arr)
{
   arr[0] = 'X';
}        
int main()
{
   function("MyString");    
   return 0;
}
  1. 在函数参数上下文中有何不同?
  2. 不会为函数参数分配内存??

请分享你的知识。

【问题讨论】:

  • 与数组参数大小的讨论无关。这是关于字符串文字与字符数组的 const-ness,这与大小几乎无关。

标签: c gcc string-literals function-parameter


【解决方案1】:

字符 *arr; 上面的语句暗示 arr 是一个字符指针,它可以指向一个字符或字符串

& 字符 arr[]; 上面的语句意味着 arr 是字符串,可以存储尽可能多的字符,甚至可以存储一个字符,但总是依赖 '\0' 字符,因此使其成为字符串 (例如 char arr[]= "a" 类似于 char arr[]={'a','\0'} )

但是当在被调用函数中作为参数使用时,传递的字符串是一个字符一个字符地存储在形式参数中,没有区别。

【讨论】:

    【解决方案2】:

    在函数参数列表内部,char arr[]char *arr是绝对等价的,所以定义对和声明对是等价的。

    void function(char arr[]) { ... }
    void function(char *arr)  { ... }
    
    void function(char arr[]);
    void function(char *arr);
    

    问题在于调用上下文。您为函数提供了字符串文字;字符串文字不得修改;您的函数试图修改它给出的字符串文字;您的程序调用了未定义的行为并崩溃了。完全符合犹太教规。

    将字符串文字视为static const char literal[] = "string literal";,不要尝试修改它们。

    【讨论】:

    • 您甚至可以说static const char 以获得正确的存储期限。
    • 事实上,C++ 标准确实指定字符串字面量为const。不幸的是,C 标准没有这样做,大概是因为这会破坏太多遗留代码,这些代码虽然没有修改这些文字,但在其声明中是草率的。
    • @microtherion:是的,您对遗产的看法是正确的。 GCC v3.x 及更早版本有一个选项-fwriteable-strings(有两个 e 的 IIRC,但可能是一个),它使字符串文字可写而不是常量。 GCC v4.x 不支持该选项;字符串文字总是不可写的。
    • 我认为第一句话可能会被误解,在函数原型中两者是相同的,而不是在函数体中。我知道这就是你的意思,但也许不是每个读者都这样。
    • @DanielFischer:我明白你的意思;修订版能解决这个问题吗?
    【解决方案3】:
    function("MyString");
    

    类似于

    char *s = "MyString";
    function(s);
    

    "MyString" 在这两种情况下都是字符串文字,并且在这两种情况下字符串都是不可修改的。

    function("MyString");
    

    将字符串文字的地址作为参数传递给function

    【讨论】:

    • 在第一种情况下,HelloWorld 仅在 char arr[] 情况下是字符串文字。对吗??
    • 在第一个代码片段中,y 的字符串文字是复制到堆栈的初始化程序。如果函数被多次调用,则数组将在每次调用时初始化,可能使用来自其他地方的常量初始化器。不过,该数组是可修改的。
    猜你喜欢
    • 2021-10-28
    • 2021-02-03
    • 2018-03-14
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    • 2018-11-28
    相关资源
    最近更新 更多