Адрес переменной в c передается по значению? - PullRequest
0 голосов
/ 28 апреля 2020

это то, как переменная передается из основного веселья c:

Node merged = NULL; 
ErrorCode result = mergeSortedLists(left, right, &merged);

и это подпись веселья c.

ErrorCode mergeSortedLists(Node list1, Node list2, Node *merged_out); 

Если произошла ошибка происходит в веселье c. отсортированные списки слияния мы должны вернуть res = Error, а слитый список должен быть NULL

преподаватель сказал, что мы должны назначить merged_out = NULL; но разве адрес не передается по значению в удовольствие c.? не следует ли присваивать переменной, на которую он указывает, значение NULL, т. е. * merged_out = NULL;

Заранее спасибо!

Ответы [ 3 ]

1 голос
/ 28 апреля 2020

Все передается по значению в C.

Так что да, &merged (указатель) передается по значению в mergeSortedLists. Другими словами, объект, на который merged_out указывает, может быть изменен в этой функции через привязку указателя, но любые изменения значения указателя в этой функции не будут отражены в вызывающей стороне.

Я не уверен, почему ваш преподаватель хочет, чтобы вы написали *merged_out = NULL в самой функции. Чтобы это имело смысл, тогда merged_out должен быть указателем на указатель с соответствующими изменениями, сделанными на вызывающем сайте.

0 голосов
/ 28 апреля 2020

Узел объединен = NULL; объединенный является указателем на пользовательскую структуру. (это делается оператором typedef), например:

struct S_Node{
    int m_var;
    struct S_Node* p_m_next;
};
typedef struct S_Node* Node;  /*now Node is new type. its pointer to S_Node*/

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

ErrorCode mergeSortedLists(Node list1, Node list2, Node *merged_out)
{
    if(!list1 || !list2) /*lets assume that this is the error case*/
    {
        *merged_out=NULL;
        return Error;
    }
}
0 голосов
/ 28 апреля 2020

Кажется, что имя Node является псевдонимом для типа указателя.

Что-то вроде

typedef struct node
{
    //...
} *Node;

Так в этом фрагменте кода

Node merged = NULL; 
ErrorCode result = mergeSortedLists(left, right, &merged);

переменная merged является указателем. И он передается по ссылке на функцию mergeSortedLists.

Это просто плохая идея ввести такой псевдоним для типа указателя, потому что он может только запутать читателей кода.

Если принять, что имя Node является псевдонимом для типа указателя (как, например,

typedef struct node *Node;

, то это объявление функции

ErrorCode mergeSortedLists(Node list1, Node list2, Node *merged_out); 

эквивалентно

ErrorCode mergeSortedLists( struct node  *list1, struct node *list2, struct node **merged_out); 

То есть все три параметра имеют типы указателей.

...