【问题标题】:Passing char pointers between functions - Are both ways equal? - C在函数之间传递 char 指针 - 两种方式是否相等? - C
【发布时间】:2018-04-08 13:12:56
【问题描述】:

我已经完成了一个将 char 指针传递给其他函数的 MCVE 代码。如果两种传递 char 指针参数的方式相等(str1str2 分别传递到 passingCharPointer1passingCharPointer2 中),我就知道了。

另外,我在代码中包含了 cmets 以及 free/null 函数的行为及其行为(如果它们也被阅读,我将不胜感激)。

代码是:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAX_LENGTH 50

void passingCharPointer1(char *str) {
    strcpy(str, "Hi-1!");
}

void passingCharPointer2(char **str) {
    strcpy(*str, "Hi-2!");
}



int main() {
    // Init char pointers
    char *str1 = malloc((MAX_LENGTH +1)*sizeof(char));
    char *str2 = malloc((MAX_LENGTH +1)*sizeof(char));

    // Gets their values
    printf("Input string 1: ");
    fgets(str1, MAX_LENGTH , stdin);
    printf("Input string 2: ");
    fgets(str2, MAX_LENGTH , stdin);
    printf("\n");

    // Remove '\n' character
    str1[strcspn(str1, "\n")] = '\0';
    str2[strcspn(str2, "\n")] = '\0';

    // Print their values
    printf("BEFORE - Function 1: %s\n", str1);
    printf("BEFORE - Function 2: %s\n", str2);

    // Pass to function in two ways - ARE BOTH WAYS EQUAL?
    passingCharPointer1(str1);
    passingCharPointer2(&str2);

    // Print their values
    printf("AFTER - Function 1: %s\n", str1);
    printf("AFTER - Function 2: %s\n", str2);

    // Freeing pointers
    free(str1);
    free(str2);

    // Print their values after freeing
    printf("\nAFTER FREE 1: %s\n", str1); // Show rare characters (I supposse it is normal behaviour after free)
    printf("AFTER FREE 2: %s\n", str2); // Continue having its content (I supposse it is not normal behaviour after free)

    // Nulling pointers
    str1 = NULL;
    str2 = NULL;

    // Print their values after nulling
    printf("\nAFTER NULL 1: %s\n", str1); // Normal behaviour
    printf("AFTER NULL 2: %s\n", str2); // Normal behaviour

    // Exit success
    return 0;
}

【问题讨论】:

  • 问题是什么?打印free-d 内存是未定义的行为。
  • 表达式:sizeof(char) 在 C 标准中定义为 1。乘以 1 无效。调用malloc() 函数的参数被这些表达式弄乱了。建议从对malloc()的调用中删除这些表达式
  • 在调用任何堆分配函数时:malloccallocrealloc,始终检查 (!=NULL) 返回值以确保操作正常
  • @s7amuser 是的,好的,谢谢。但是,一个显示内容而另一个不显示内容是正常的,对吧?
  • 发布的代码包含一些“神奇”数字。 “魔术”数字是没有基础的数字。 IE。 50. 'magic' numbers 使代码更难理解和调试。建议使用#define 语句或enum 语句为这些“神奇”数字赋予有意义的名称,然后在整个代码中使用这些有意义的名称。

标签: c pointers char


【解决方案1】:

一般来说,这些功能是不等价的。第一个函数通过值接受指针,而第二个函数通过引用接受指针。因此,第二个函数可以更改表达式中用作参数的原始指针。

考虑以下演示程序

#include <stdio.h>

void passingCharPointer1( char *s ) 
{
    s = "Bye";
}

void passingCharPointer2( char **s )
{
    *s = "Bye";
}

int main(void) 
{
    char *s1 = "Hello";
    char *s2 = "Hello";

    printf( "Before function calls: %s %s\n", s1, s2 );

    passingCharPointer1( s1 );
    passingCharPointer2( &s2 );

    printf( "After function  calls: %s %s\n", s1, s2 );

    return 0;
}

它的输出是

Before function calls: Hello Hello
After function  calls: Hello Bye

注意在释放内存后访问内存会调用未定义的行为。

【讨论】:

  • 好的,谢谢您的提问。然后,通过引用传递指针应该是:&amp;,不是吗?另外,如果我按值传递(不带&amp;)并执行strcpy 也会更改指针中包含的值,因为它是通过引用传递的……那为什么呢?
  • 我的意思是,通过值传递我也可以修改它的内容
  • @JuMoGar 当参数的类型为 char * 时,表示对象(即数组的字符)是通过引用传递的,并且可以使用指针进行更改。要更改原始指针本身,您必须通过使用指向指针的指针的引用依次传递它。
  • 好的,我明白了。但是,通过引用传递指针有什么用处(因此,接收指针指针)?改变它指向的内存地址?还是为了别的?
  • @JuMoGar 例如,许多列表函数,例如将新节点添加到列表中,通过引用接受列表头,因为指向头的指针可以在函数中更改。
【解决方案2】:

如果你的问题是真的:

两种传递参数的方式(函数1和函数2)都相等

(并且您忽略了main() 中的所有代码),那么是的,这两个功能本质上是等价的。

不同之处在于 function1 接受一个指向 char 的指针(在 C 语言中,它是一个字符串的习惯用法),而 function2 接受一个指向 char 的指针。

但正如莫斯科的@Vlad 指出的那样,function2 允许您修改传递给函数的指针。

【讨论】:

  • 哦,好的,谢谢。修改指针传递的出现是什么?我的意思是,如果我不使用&amp; 传递它,我也可以修改它的值,所以... 使用&amp; 传递指针的冒险(或不)是什么?
  • > 这是传递指针的冒险(或不是)...这很简单:如果您不需要修改指针,请使用 function1 - 它节省了一点计算,但是更重要的是,明确你的意图。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-13
  • 2015-04-29
  • 2011-05-22
  • 2012-12-29
  • 1970-01-01
  • 2021-09-07
  • 2021-12-02
相关资源
最近更新 更多