Fred
Fred

Reputation: 579

How do you return an array literal in c?

Here is a C function that returns an array with a type defined in a struct. It successfully returns the array p. My question: can I eliminate p and do a return as shown in the commented-out statement?

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

I get "error: expected expression before '{' token" for the line I've commented out.

Upvotes: 1

Views: 777

Answers (3)

ryyker
ryyker

Reputation: 23218

No, but you can return a pointer to any construct, including arrays and structs using identical approaches. eg:

Given the prototype M *boom (int x), the following demonstrates how you can pass back an instance of M struct data after having modified it.

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

This method can be used exactly the same way with arrays:

Given the following function:

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

In main():

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

Upvotes: 1

klutt
klutt

Reputation: 31389

No you cannot.

The closest I can think if that you can return a compound literal. Example:

struct myStruct {
    int x;
    int y;
};

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

But you cannot do this with arrays. As Eric Postpischil said in the comments:

To be clear, this is not because compound literals cannot be arrays. They can. It is because an array cannot be returned by value, and its address, or the address of its first element, cannot properly be returned because the array’s lifetime would end with the function return.

Something that is possible if you restrict yourself to fixed size arrays is to wrap the array in a struct:

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

I might also mention that even if returning addresses to local static variables is perfectly legal, it is widely considered a strong code smell.

Upvotes: 3

fpf3
fpf3

Reputation: 424

Array literals can only be used for initialization. They can't be passed around like string literals or integers or floats.

Upvotes: 1

Related Questions