Обоснование для передачи указателя как параметра функции и возврата его в C - PullRequest
4 голосов
/ 09 сентября 2011

Я изучаю исходный код (написанный на C) bkhive - утилиты для сброса загрузочного ключа SysKey из системного куста Windows NT / 2K / XP - и хотел бы узнать, есть ли какое-то обоснование для чего-либо оригинальный автор сделал: передать указатель на struct в функцию и затем вернуть тот же указатель. Вот соответствующий исходный код:

В main() есть вызов, который выглядит следующим образом:

struct hive h;
char *root_key;
// Do some stuff to init
_RegGetRootKey(&h, &root_key)

Какие звонки:

int _RegGetRootKey(struct hive *h, char **root_key)
{
    nk_hdr *n;
    n = (nk_hdr*) malloc(sizeof(nk_hdr));

    /* ************************************************
     * RELEVANT FUNCTION CALL
     * Why pass n as a parameter and use return value?
     * ************************************************/
    n = read_nk(n, h, 0x1020);

    if (n->id == NK_ID && n->type == NK_ROOT)
    {
        *root_key = (char *) malloc(n->name_len + 1);
        strncpy(*root_key, n->key_name, n->name_len);
        (*root_key)[n->name_len] = 0;
        free(n);
        return 0;
    }
    free(n);
    return -1;
}

Какие звонки:

nk_hdr* read_nk(nk_hdr *nk, struct hive *h, int offset)
{
    memcpy(nk, h->base + offset + 4, sizeof(nk_hdr));
    nk->key_name = (h->base + offset + 4 + 76);
    return nk;
}

Итак, какова цель передачи указателя struct и его возврата? Может ли функция ничего не возвращать и использовать n после вызова функции?

Ответы [ 3 ]

4 голосов
/ 10 сентября 2011

Основным преимуществом этого соглашения является упрощение объединения вызовов функций. Если вы хотите использовать возврат одной функции в качестве параметра другой функции, то при ее возврате указатель может позволить записать инструкцию в одну строку. Таким образом, вместо того, чтобы писать что-то вроде этого:

foo(myPtr);
bar(myPtr);

Вы можете сделать это:

bar(foo(myPtr));

Конкретный код, который вы показываете, не использует это, но это соглашение используется во многих функциях C, и я думаю, автор кода уже привык к этому.

1 голос
/ 10 сентября 2011

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

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

Другое, даже если указатель не изменится, - это то, что он позволяет немедленно использовать возврат из функции для доступа к указанному элементу.в таких конструкциях, как somefunc(item)->member = 5; среди других.Это позволяет перенести вызов функции в другое выражение, которому впоследствии потребуется тот же указатель.

Это также может быть сделано просто для согласования использования функции с другими в API, некоторые из которых могут иметь причину для этого.

1 голос
/ 10 сентября 2011

Это позволяет вам передать объект по ссылке, а затем получить дескриптор (т. Е. Указатель) к обновленному значению при возврате ... он также позволяет вам возвращать NULL, если что-то идет не так, чтобы вы знали, состояние объекта, который вы передали по ссылке, больше не является хорошим. Например:

struct my_struct* pass_by_ref = malloc(sizeof(my_struct));
//...some more code

if (foo(pass_by_ref) == NULL)
{
    free(pass_by_ref); //pass_by_ref is no longer any good ...
    perror();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...