【问题标题】:How to change a pointer value between functions如何在函数之间更改指针值
【发布时间】:2019-09-23 14:30:55
【问题描述】:

我是 C 新手,对如何在函数之间更改 char * 的值感到困惑。

例如:

#include <stdio.h>
void testing(char *s) {
        s = "hi";
} // testing

int main() {
        char *s = "hello";
        testing(s);
        printf("%s\n", s);
} // main

在这种情况下,s 的值没有改变,并打印"hello"

如何更改s,而无需更改任一函数的返回类型或参数?

【问题讨论】:

  • 不幸的是,很难很好地回答这个问题。原因是您似乎对指针和字符串文字没有足够的基础知识。我可以编写适合您的代码,但这会令人困惑。我建议阅读有关字符串、指针和字符串文字的内容。
  • @klutt。我不知道,我有点喜欢我的回答
  • @MadPhysicist 我不确定。我觉得虽然它在技术上是正确的,但我怀疑它是否教会了 OP 他真正需要知道的东西。
  • @klutt。除非我们永远无法真正了解某人的想法,否则我进行了更新。

标签: c pointers char


【解决方案1】:

C 函数调用是严格按值传递的。这意味着当您将s 传递给testing 时,会生成一个本地副本。因此,在函数中为s 分配新值不会影响main 中的值。

由于指针的值被复制,但是,您可以访问它指向的内存。如果s 指向非只读内存,您可以将一个缓冲区的内容复制到另一个缓冲区。例如,而不是s = "hi";

strcpy(s, "hi");

main 中,char *s = "hello"; 语句很可能让s 指向只读缓冲区。要使其成为可写缓冲区,请将 s 声明为数组:

 char s[] = "hello";

如果你想改变指针的值,而不是它指向的东西,你需要传入包含mains版本的内存地址:指向指针的指针。看起来像这样:

#include <stdio.h>
void testing(char **s) {
        *s = "hi";
} // testing

int main() {
        char *s = "hello";
        testing(&s);
        printf("%s\n", s);
} // main

另一种(在这种情况下可能更好)方法是使用返回值而不是输入和输出的参数:

#include <stdio.h>
char *testing(char *s) {
        s = "hi";
        return s;
} // testing

int main() {
        char *s = "hello";
        s = testing(s);
        printf("%s\n", s);
} // main

【讨论】:

    【解决方案2】:

    main 中,char *s 被初始化为字符串文字"hello"。这意味着s 将指向包含{ 'h', 'e', 'l', 'l', o', '\0' } 值的6 个char 的匿名数组。但是,就标准而言,该数组的内容是不可修改的,因此写入该数组的任何代码都会表现出未定义的行为

    在对testing 的调用中,参数char *s 被视为函数内的局部变量。对指针值的任何更改都不会影响main 中的char *s 变量。在 C 函数调用中,所有参数都按值传递

    testing 中,您将s 更改为指向另一个字符串文字"hi"。与main 中的初始化类似,testings 现在将指向包含值{ 'h', 'i', '\0' } 的3 个char 的匿名数组。此匿名数组的内容不可修改。如上所述,这对mains 指针没有影响。

    您声明不希望修改任一函数的参数或返回类型。为此,testing 将需要覆盖其参数s 指向的数组的内容。由于main 中的当前代码有s 指向不可修改的数组,因此您需要将其更改为指向可修改的数组。这可以通过将mains 更改为数组而不是指针来完成:

    int main() {
            char s[] = "hello"; // N.B. s[] is 6 chars long including the null terminator
            testing(s);
            printf("%s\n", s);
    } // main
    

    那么你可以改变testing来覆盖其参数s所指向的数组的内容:

    #include <string.h>
    
    void testing(char *s) {
            strcpy(s, "hi");
    } // testing
    

    我在上面的testing版本中使用了strcpy标准库函数。

    您可以确保不要将过多的chars 写入s 指向的数组。

    main 中数组 s 的长度已被初始化程序“hello”自动设置为 6(5 个字符加上一个空终止符)。如果您需要覆盖超过 6 个 chars 包括空终止符,您可以显式设置数组的长度:

        char s[100] = "hello";  // s[100] has space for 99 characters plus a null terminator.
    

    【讨论】:

      【解决方案3】:

      函数只接收参数值的副本:

      void f(int x)          // x is a new variable that is initialized to the argument value.
      {
          x = x + 3;         // Adds 3 to the local x.
          printf("%d\n", x); // Prints 8.
      }
      
      int main(void)
      {
          int x = 5;
          f(x);              // Passes 5, not x, to f.
          printf("%d\n", x); // Prints 5, not 8.
      }
      

      你可以通过返回函数从函数中取回一个值:

      int f(int x)           // Function is changed to return int.
      {
          x = x + 3;         // Adds 3 to the local x.
          printf("%d\n", x); // Prints 8.
          return x;          // Returns new value.
      }
      
      int main(void)
      {
          int x = 5;
          x = f(x);          // Set x from the value returned by the function.
          printf("%d\n", x); // Prints 8.
      }
      

      您还可以通过让函数更改对象的值来从函数中获取值。为此,您必须向函数提供对象的地址:

      void f(int *p)          // p is a pointer to an int.
      {
          *p = *p + 3;        // Adds 3 to the pointed-to int.
          printf("%d\n", *p); // Prints 8.
      }
      
      int main(void)
      {
          int x = 5;
          f(&x);             // Passes address of x to f.
          printf("%d\n", x); // Prints 8.
      }
      

      如果你想让一个函数改变一个指针,你可以传递一个指针的地址:

      void f(char **p)       // p is a pointer to a pointer to a char.
      {
          *p = "hi"          // Sets *p to point to (first character of) "hi".
          printf("%s\n", x); // Prints "hi".
      }
      
      int main(void)
      {
          char *s = "hello"; // Sets s to point to (first character of) "hello".
          f(&s);             // Passes address of s to f.
          printf("%s\n", x); // Prints "hi".
      }
      

      【讨论】:

        猜你喜欢
        • 2012-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多