【问题标题】:Define new function, array, struct etc inside of parameter of function call [duplicate]在函数调用的参数中定义新函数、数组、结构等[重复]
【发布时间】:2017-01-03 18:20:48
【问题描述】:

如果您有一个采用以下功能的函数:

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);

【问题讨论】:

  • 我建议您在一个新问题中提出第二个完全不相关的问题。提示:先做一些研究...... :)
  • 简答:C 不是 Java。有些事情在 C 中无法像在 Java 中那样完成。这是其中之一。你会发现 C 程序员会感激你的 Java 方式无法做到这一点。

标签: c arrays function pointers compound-literals


【解决方案1】:

您如何执行以下操作:

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() 的调用周围加上大括号,创建一个本地范围/块:

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. */

  ...

【讨论】:

    【解决方案2】:

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

    如果是我,我会避免 [太努力] 将 C 强制转换为“类 Java”。拥抱每种语言的优点。

    对于您的第一个示例,“丑陋”的示例,您可以使用 CPP [C 预处理器]宏——Java 中不存在 的概念:

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

    但是,这可能会被许多人认为“太可爱了”。最好创建某种表格。

    每当Java 执行new 时,它都会执行堆分配[这很慢]。这部分是因为所有东西或多或少都必须“在堆上”。

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

    【讨论】:

    • “但是,这可能会被很多人认为是“太可爱了”。”,或者太... :P :P :P 无论如何,幸好我们有替代我的答案,+ 1.. :)
    【解决方案3】:

    你一定是那些以开头然后试图进入的人的另一个受害者,这就是我要回答的原因。

    我想在该参数内初始化我的数组。怎么可能?

    您不能。 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 结尾。

    【讨论】:

    • 很抱歉,您似乎没有阅读我的问题。看到你在哪里输入了foo(x, 3)?我想初始化我的数组 inside 该参数。那怎么办?
    • @Hatefiend 我做到了。你不能。
    • 传递长度的替代方法是在char* 数组的末尾添加一个NULL 标记,因此foo 可以继续,直到arr[i] 为NULL。显式长度通常更好,但哨兵有时很有用。
    • 我也不能在参数中声明函数?
    • @ShadowRanger 更新了,你怎么看?聪明的主意!讨厌鬼,不,但你可以传递一个函数指针,正如你已经知道的那样...... ;)
    猜你喜欢
    • 2019-01-14
    • 1970-01-01
    • 2020-09-04
    • 2020-02-12
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 2018-09-14
    • 2016-02-08
    相关资源
    最近更新 更多