【问题标题】:How do you return an array literal in c?你如何在c中返回一个数组文字?
【发布时间】:2021-03-08 16:59:53
【问题描述】:

这是一个 C 函数,它返回一个在结构中定义的类型的数组。它成功返回数组 p。我的问题:我可以消除 p 并按照注释掉的语句中所示的方式返回吗?

#include<stdio.h>

typedef struct {
    int dy, dx, iter;
} M;
  
M *boom (int x) {

    // I'm happy with this approach
    static M p[] = { {+5, +6, +7}, {+1, +1, +0}, {+3, +3, +3} };
    return p;
    // but I'm keen to know how this can be done.
//    return { {+5, +6, +7}, {+1, +1, +0}, {+3, +3, +3} };  // causes error
}

int main() {
    M *result = boom(1);
    printf("First element %d\n", result[2].dy);
}

对于我已注释掉的行,我收到“错误:'{' 标记之前的预期表达式”。

【问题讨论】:

    标签: arrays c return


    【解决方案1】:

    不,你不能。

    如果您可以返回复合文字,我能想到的最接近的。示例:

    struct myStruct {
        int x;
        int y;
    };
    
    struct myStruct foo() {
        return (struct MyStruct) {.x =5, .y=6};
    }
    

    但是你不能用数组来做到这一点。正如 Eric Postpischil 在 cmets 中所说:

    需要明确的是,这并不是因为复合文字不能是数组。他们能。这是因为一个数组不能按值返回,它的地址,或者它的第一个元素的地址,不能正确返回,因为数组的生命周期会随着函数返回而结束。

    如果您将自己限制为固定大小的数组,则可以将数组包装在一个结构中:

    struct myStruct {
        int x;
        int y;
    };
    
    struct myContainer {
        struct myStruct arr[3];
    };
    
    struct myContainer foo() {
        return (struct myContainer) { 
            .arr={{.x =5, .y=6}, {.x=4, .y=1}, {.x=42, .y=665}}
        };
    }
    

    我还可能提到,即使将地址返回给本地静态变量是完全合法的,但它被广泛认为是一种强烈的代码气味。

    【讨论】:

    • 仅注意compound literals 需要 C99 或更高版本的标准编译器 (+1)。
    • @dxiv 是的,但这就像在说“请注意,你需要一个至少支持 256 色的显卡才能玩这个游戏”:D
    • @klutt MSVC 等到 2013 支持 C 中的复合文字除外 ;-)
    • @dxiv 我不得不承认你说得有道理。但是,如果有人尝试使用 C99 之前的编译器进行此操作,他们会立即注意到出现了问题。而且我认为无论我是否添加该信息,他们都会在此处发布问题。 ;)
    • @dxiv:微软没有 C 编译器。 MSVC 是一个具有一些 C 特性的 C++ 编译器。通常不应将其视为与 C 讨论相关。
    【解决方案2】:

    不,但您可以将 指针 返回到任何构造,包括使用相同方法的数组和结构。例如:

    给定原型M *boom (int x),下面演示了如何在修改后将M 结构数据的实例传回。

    typedef struct {
        int dy, dx, iter;
    } M;
      
    M *boom (int x) {
    
        M *new = malloc(sizeof(*new));
        if(new)
        {
            //modify new instance of M
            new->dx = x;
            //and so on
        }
    
        return new;
    }
    
    int main() {
        M *result = boom(1);
        printf("First element %d\n", result[2].dy);
        free(result);
    }  
    

    此方法可以与数组完全一样的方式使用:

    给定以下函数:

    int * func(int *array, size_t size, int index, int newValue)
    {
         int *newArray = malloc(size * sizeof(*newArray));
         //modify as much of original array as needed:
         newArray[index] = newValue;
         return newArray;
    }    
    

    在 main() 中:

    int *a = func(array, sizeof(array), 2, 100);
    printf("new value for element %d is %d\n", 2, a[2]);
    free(a);
    

    【讨论】:

    • @Bob Jones - 你删除了here 的一个问题,因此是一个答案,我相信这对很多人来说都是有用的。请考虑重新开放。
    【解决方案3】:

    数组字面量只能用于初始化。它们不能像字符串文字或整数或浮点数一样传递。

    【讨论】:

    • static M p[] = { {+5, +6, +7}, {+1, +1, +0}, {+3, +3, +3} }; 中的初始化器不是数组字面量。根据 C 2018 6.7.9,它们只是初始化器列表。复合字面量也是如此,复合字面量可以是数组,但不能正确地从函数返回,因为它的生命周期会以函数返回结束。
    猜你喜欢
    • 1970-01-01
    • 2011-11-29
    • 2014-11-22
    • 1970-01-01
    • 2020-07-24
    • 2014-12-18
    • 2016-05-03
    • 2011-01-25
    • 2012-10-04
    相关资源
    最近更新 更多