Есть ли способ заставить переменную пережить 1 область видимости из текущей? - PullRequest
0 голосов
/ 12 октября 2019

Я хочу создать функцию, которая возвращает указатель на локально определенную переменную. Ради аргумента я вызову функцию struct awesome *makeCoolStruct() (я не хочу объявлять переменную во внешней области видимости, которая должна иметь вызов struct awesome coolness = makeCoolStruct();, потому что функция будет вызываться более чем в одном месте).

Я понимаю, почему компилятор выдает ошибку, когда я пытаюсь это сделать - локальная переменная будет «уничтожена», как только программа выйдет из этой области, поэтому указатель в основном будет недействительным.

Я посмотрел, как вернуть указатель на локальную переменную в функции, и, хотя я понимаю, почему malloc будет работать, это лишает цели попытки сделать это таким образом, потому что malloc, насколько я понимаю,хранит переменную до тех пор, пока работает программа - или до вызова free. Однако это означает, что мне нужно будет вызывать free в конце всего, что вызывает мою функцию. В этот момент лучше объявить переменную в каждой вызывающей области, а затем передать указатель на нее, например makeCoolStruct(&existingVariable);.

Если, однако, есть способ объявить «оставьте эту переменную для 1«Положение выше в стеке» (что, очевидно, приведет к ошибке компиляции в глобальной области видимости, так как в стеке нет более высоких позиций), тогда я мог бы вернуть указатель, и он будет существовать очень хорошо, пока он мне нужен, где бы я ни решил позвонить struct awesome x = makeCoolStruct(); (я знаю о проблемах изменчивости - я не ищу изменчивость). С этого момента я мог действительно вернуть все, что захочу, в функции, а не только то, что было передано.

Я действительно ничего не пробовал, потому что не знаю ничего, что могло бы сработать.

Я ожидаю, что смогу вернуть указатель на локальную переменную после того, как что-либо удерживает переменную на одну область выше, без необходимости какой-либо подготовки к вызову функции, когда я ее вызываю (создание переменной для ее использования. для вывода вместо того, чтобы просто присвоить вывод чему-либо.

Ответы [ 2 ]

3 голосов
/ 12 октября 2019

То, что вы спрашиваете, невозможно в C, но есть несколько альтернатив:

Передача переменной стека в:

typedef struct {
    int a;
    int b;
} Foo;

void bar(Foo* foo)
{
    foo->a = 5;
}

int main(void)
{
    Foo foo = {0};
    bar(&foo);
    return 0;
}

Прямой возврат структуры:

Foo bar(void)
{
    Foo foo = {1, 2};
    return foo;
}

int main(void)
{
    Foo foo = bar();
    return 0;
}

Управление памятью вручную :

Foo* bar(void)
{
    Foo* foo = malloc(sizeof(*foo));
    return foo;
}

int main(void)
{
    Foo* foo = bar();
    free(foo);
    return 0;
}

Наконец, если вы действительно ненавидите того, кто собирается это унаследоватьпроект, вы всегда можете использовать макрос:

#define FOO(X)     \
    Foo X = {0};   \
    bar(&X);
0 голосов
/ 12 октября 2019

Хотя это и не рекомендуется, на самом деле безопасно возвращать указатель на статическую переменную, предполагая, что ваша программа не многопоточная.

struct myStruct {
    int x;
    char y;
};

struct myStruct *foo() 
{
    static struct myStruct bar = {.x = 0, .y = 'a'};
    return &bar;
}

Я бы никогда не написал что-то подобное, но это безопасно вчувствую, что это не вызывает неопределенного поведения.

И на всякий случай, если вы не знали, было бы здорово вернуть структуру. Вам не нужен malloc для этого. Это было бы хорошо:

struct myStruct foo() 
{
    struct myStruct bar = {.x = 0, .y = 'a'};
    return bar;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...