【问题标题】:Changing an array with a function in C?在 C 中使用函数更改数组?
【发布时间】:2011-08-02 11:32:31
【问题描述】:

我想调用一个函数,我希望该函数将程序中的字符串或数组的内容更改为常量。

伪代码:

some_array = "hello"
print some_array   #prints "hello"
changeArray(some_array)
print some_array  #prints "bingo"

我知道我必须将指针传递给该函数。这是我写的,

void changeArray(char *arr){
    arr = "bingo";
}

int main(int argc, const char* argv[]){
    char *blah = "hello";
    printf("Array is %s\n",blah);
    changeArray(blah);
    printf("Array is %s\n",blah);
    return EXIT_SUCCESS;
}

我该怎么做?

【问题讨论】:

    标签: c arrays function pointers


    【解决方案1】:

    您通过值而不是通过引用传递指向数组的指针。应该是:

    void changeArray(char **arr){
        *arr = "bingo";
    }
    
    int main(int argc, const char* argv[]){
        char *blah = "hello";
        printf("Array is %s\n",blah);
        changeArray(&blah);
        printf("Array is %s\n",blah);
        return EXIT_SUCCESS;
    }
    

    您将“hello”的地址提供给changeArray 函数,但在函数中您更改了传递的值,而不是原始指针。我所做的更改传递了指针的地址,而指针本身在函数中发生了更改。

    请不要char *blah = "hello";定义一个指向常量字符串的指针,以及*arr = "bingo";,这两者都可以,但是如果你考虑改变字符串本身,你将无法做到。

    编辑:

    当您将参数(甚至是指针)传递给函数时,实际上是将其复制到函数从那里读取它的某个位置(通常是堆栈)。您不会传递参数本身,而是传递它的副本。当函数修改它时(如在arr = "bingo"; 中),它会修改变量的副本,而不是原始变量。所以为了改变变量本身,我们将变量的地址传递给函数(changeArray(&blah); - & 表示address of-)并在函数中修改存储在我们传递的地址中的变量(@987654329 @ - * 表示地址 arr 中的变量。

    假设原来的blah指针位于地址0x00000000并且包含"hello"字符串的地址,例如0x00000010。如果将blah 传递给函数,则将其复制到一个新变量arr,例如位于地址0x00000020 中

    Variable    Address     content
    -------------------------------
    blah       00000000    00000010   (points to hello)
    "hello"    00000010    "hello" (this is just an example, so don't be hard on me :) )
    arr        00000020    00000010
    "bingo"    00000030    "bingo" (and again...)
    

    现在,如果您更改arr 的内容,您会更改地址 0x00000020 中的值,但不会更改地址 0x000000000 中的值,因此blah 仍然包含 00000010。

    Variable    Address     content
    -------------------------------
    blah       00000000    00000010   (points to hello)
    "hello"    00000010    "hello" (this is just an example, so don't be hard on me :) )
    arr        00000020    00000030 (points to "bingo")
    "bingo"    00000030    "bingo" (and again...)
    

    我们所做的是将blah的地址,即0x00000000复制到arr,在函数中我们说-“arr的内容是一个地址,去这个地址,把它的内容改成指向“bingo”字符串。所以现在地址 0x00000000(即blah)中的内容指向“bingo”。

    Variable    Address     content
    -------------------------------
    blah       00000000    00000030   (points to "bingo")
    "hello"    00000010    "hello"    (this is just an example, so don't be hard on me :) )
    arr        00000020    00000000   (points to `blah`)
    "bingo"    00000030    "bingo"    (and again...)
    

    希望我没有把你弄糊涂……

    【讨论】:

    • 无论如何,改写你的答案。数组总是在 C 中通过引用传递。如果 OP 希望更改数组的内容,OP 应该更改每个位置的元素。对于字符数组(字符串),OP 应该使用strcpy() 或其他字符串函数。
    • @Andre - 感谢您的评论,我将其更改为“指向数组的指针”,但指针通过值而不是通过引用传递仍然是正确的。再次感谢。
    • @AndréCaron:这是一个误导性的看待它的原因。在 C 中,数组从不传入或传出函数。所有看起来像接受数组的函数实际上都接受指针,声明返回数组的函数是非法的。在 C 中,所有参数(包括指针)始终按值传递给函数。C 是一种仅“按值传递”的语言。
    • 非常感谢。我不太明白 *arr 和 **arr 之间的区别。
    • @André 你错了; C 仅按值传递。用作右值的数组被隐式转换为指向其第一个元素的指针。当右值作为参数传递给函数时,指针按值传递。所有这些都在 C 标准中明确明确地说明;我敦促你阅读它。如果 OP 使用 strcpy,这将导致未定义的行为(并且在大多数实现中会因违反内存保护而崩溃),因为 blah 指向一个无法写入的字符串常量。
    【解决方案2】:

    您的代码中没有数组。如果您实际上是在尝试修改 blah 字符指针指向的内容,则需要将指向指针的指针传递给函数。 但是,如果您想使用数组执行此操作,则需要执行以下操作:

    void changeArray(char arr[]) {
      // or you can use char *arr, it's the same thing from
      // the C compiler's point of view
      strcpy(arr, "blah");
      // alternatively, you could set each element. i.e. arr[0] = 'b';
    }
    
    int main (int argc, char** argv) {
      char blah[100] = "hello"; // this is an array
      printf("Array is %s\n", blah);
      changeArray(blah);   // array decays to pointer
      printf("Array is %s\n", blah);
      return EXIT_SUCCESS;
    }
    

    【讨论】:

    • 谢谢,用好strcpy()。我有一个任务要做,我不能使用 **arr 作为更改函数中的参数,所以这很完美。
    • @Ferruccio 为什么不需要&changeArray(blah)
    • @cokedude - 您实际上不能将数组作为参数传递给 C 中的函数。数组将“衰减”为指向数组第一个元素的指针,因此调用 changeArray(blah)changeArray(&blah[0])。由于函数声明为void changeArray(char arr[]),与changeArray(char* arr) 相同,因此调用与函数签名匹配。
    • 值得注意的是,该数组有 100 个位置,以确保字符不会溢出到堆栈中的另一个位置。以前我们没有这样做,因为在 C 中,当您将一些字符串之间的引号分配给指针时,您实际上将指针指向代码段而不是内存堆栈的位置。
    • FWIW,我总是用数组编写代码,因为这个 void changeArray(char *arr) 但是在我正在使用的这个 IDE 上它不起作用。我不得不使用你使用的符号。我想知道它是否是这个编译器/ide 集的错误。
    【解决方案3】:

    你需要传递一个指向数组的指针而不是数组本身。

    另一件事:为你的函数添加一个控制条件。想一想:如果“bingo”大于 strlen(some_array) 会发生什么?它会给你一个错误,因为在 C 中,如果你需要动态数组大小,你必须 malloc 它!

    【讨论】:

    • 这是不正确的,他不是在复制字符串,而是将他的指针指向新的字符串。此代码示例中不需要分配。
    猜你喜欢
    • 2016-04-22
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    • 2020-10-20
    • 1970-01-01
    • 2012-10-23
    相关资源
    最近更新 更多