在函数调用的参数内部定义新函数、数组、结构等

Define new function, array, struct etc inside of parameter of function call

如果您有一个采用以下内容的函数:

void foo(char **arr);

你如何做到以下几点:

void foo(char* x[] = { "hello", "my", "friend" });

如果这让您感到困惑,在 Java 中,我们通过以下方式做到这一点:

public void foo(String[] x);

foo(new String[] { "hello", "my", "friend" });

目前,我在 C 中做了以下我讨厌的事情,因为它看起来非常丑陋:

char* myArr[] = 
    { 
        "hello", "my", "friend"
    };

foo(myArr);

你一定是又一个以 and then trying to get into 开头的人的受害者,所以我会回答。

I want to initialize my array inside of that parameter. How can that be done?

你不能。 C99 之前


一般来说,您可以这样做:

#include <stdio.h>

void foo(char** arr, int size)
{
    int i;
    for(i = 0; i < size; ++i)
        printf("%s\n", arr[i]);
}

void bar(char** arr)
{
    while(*arr)
        printf("%s\n", *arr++);
}

int main(void)
{
    char* x[] = { "hello", "my", "friend" };
    foo(x, 3);

    char* null_terminated[] = { "ShadowRanger", "Correct", NULL };
    bar(null_terminated);

    return 0;
}

其中 foo() 明确使用数组的大小,而 bar() 要求数组以 NULL 终止。

Java和C是不同的语言,有不同的习语。

如果是我,我不会[太努力]强迫C进入"Java-like"。拥抱每种语言的优点。

对于您的第一个示例,"ugly",您可以使用 CPP [C 预处理器]——这个概念 存在于 Java:

#define FOO(_av...) \
    do { \
        char *myArr[] = { _av, NULL }; \
        foo(myArr); \
    } while (0)

FOO("hello", "my", "friend");

但是,这可能会被许多人视为 "too cute"。最好创建某种 table。

每当 Java 执行 new 时,它都在进行堆分配 [这很慢]。部分原因是 一切 或多或少都必须 "on the heap"。

C 可以用 malloc 做到这一点,但优秀的 C 程序员会尽量避免不必要的堆分配,因为它有全局变量、静态变量和函数作用域变量。

How can you do the following:

void foo(char* x[] = { "hello", "my", "friend" });

您差一点就成功了……;-)

如果使用 C99 或更新版本,请使用如下复合文字:

foo((char *[]){"hello", "my", "friend"});

请注意被调用函数(foo() 这里)不知道指针数组有多少个元素,所以你想添加一个最终的空指针作为标记:

foo((char *[]){"hello", "my", "friend", NULL});

示例:

#include <stdio.h>
#include <stdlib.h> /* for EXIT_xxx macros */


void foo(char **arr)
{
  while (arr && *arr)
  {
    printf("%s\n", *arr);
    ++arr;
  }
}

int main(void)
{
  foo((char *[]){"hello", "my", "friend", NULL}); /* Mind the final NULL. */

  return EXIT_SUCCESS;
}

这将打印:

hello
my
friend

复合文字有效,直到它定义的范围被保留(此处为main())。如果您想确保它在使用后立即从堆栈中删除,请将对 foo() 的调用用大括号括起来,从而创建一个本地 scope/block:

int main(void)
{
  {
    foo((char *[]){"hello", "my", "friend", NULL}); /* Mind the final NULL. */
  }

  /* The compound literal passed to foo() is already deallocated here, had been 
     removed from the stack. */

  ...