有多少种方法可以将 char 数组传递给 C 中的函数?

How many ways are there to pass char array to function in C?

这些有什么区别?

有什么方法可以修改作为参数传递的数组元素,就像我们使用 & 传递 intfloat 和实际参数的值被修改了吗?

场景:您正在使用数组作为参数调用函数。

那样的话,

 foo(char *s)

 foo(char s[])

视为等同。他们都希望用 char 数组调用。

OTOH,foo(char *s[ ]), 不同,因为它采用 char * 数组的地址。

在 C 中不可能按值传递数组。您列出的每个可行解决方案(不幸的是不包括#2)不仅会让您,而且会强制您修改原始数组。

由于参数衰减,foo(char* s)foo(char s[]) 完全等价。在这两种情况下,您都传递带有名称的数组:

char array[4];
foo(array); // regardless of whether foo accepts a char* or a char[]

在这两种情况下,数组都被转换为指向其第一个元素的指针。

指向数组的指针解决方案不太常见。它需要以这种方式制作原型(注意 *s 周围的括号):

void foo(char (*s)[]);

没有括号,您要求的是一个字符指针数组。

在这种情况下,要调用该函数,您需要传递数组的地址:

foo(&array);

每次要访问数组元素时,您还需要从 foo 取消引用指针:

void foo(char (*s)[])
{
    char c = (*s)[3];
}

就是这样,不是特别方便。但是,它是唯一允许您指定数组长度的形式,您可能会发现它很有用。这是我个人的最爱之一。

void foo(char (*s)[4]);

如果您尝试传递的数组没有恰好包含 4 个字符,编译器将警告您。此外,sizeof 仍按预期工作。 (明显的缺点是数组必须具有准确数量的元素。)

foo(char *s), foo(char *s[ ]), foo(char s[ ]) , what is the difference in all these ?

在这些 foo(char *s)foo(char s[ ]) 中都期望 char array 作为参数。

异常剩余 -foo(char *s[ ]) 这将期望一个指向字符的指针数组作为参数。

  • foo(char *s) 非常简单,它只是一个指针,可能是指向数组第一个元素的指针。

  • foo(char s[]) 是 char 数组的声明,但是由于 C 标准中的(愚蠢的)规则,它被转换为指向 char 的指针。同样,如果您声明任何数组大小,您仍然会得到一个指向 char.

    的指针

    提到的规则可以在C11 6.7.6.3 Function declarators中找到:

    A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’

    如果完全禁止这种奇怪的、令人困惑的 "would-be-array" 语法可能会好得多,因为它是 100% 多余的,除了让试图加入 [=49] 的初学者感到困惑之外别无他用=].但后来 C 从来都不是一种理性语言...

    有些人会说,理由是出于性能原因,永远不应该允许在 C 中按值传递数组。嗯,运气不好,因为尽管有这条规则,你仍然可以。

  • 您可以 "hack the C standard" 并按值传递数组:

    typedef struct
    {
      char array[10];
    } by_val_t;
    
    foo (by_val_t arr);  // bad practice but possible
    

    现在真的没有理由要按值传递数组,这是非常糟糕的程序设计,没有任何意义。我只是在这里举这个例子来证明6.7.6.3中的规则完全没有任何理由。

  • 您可以将数组指针作为参数传递给函数。这是事情变得先进的地方,因为这很晦涩并且实际用途非常有限:

    foo(char(*s)[])
    

    如果您在此处指定数组大小,实际上会增加一些类型安全性,因为编译器往往会对不同大小的数组指针之间的转换发出警告。

    但是请注意,数组指针主要只是为了使C语言更加一致。您想要将数组指针传递给函数的原因很少( 是一个有点复杂的示例,我显然找到了它的有效用途)。