2014-10-17 2 views
1

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

+0

Возможный дубликат [лучше ли в C++ проходить по значению или передавать постоянную ссылку?] (Http://stackoverflow.com/questions/270408/is-it-better-in-c-to-pass- by-value-or-pass-by-constant-reference) – 2501

+3

@ 2501 Нет. Даже не. – Qix

+0

Это тестовый вопрос?(просто любопытно) – ryyker

ответ

6

Передаёт указатель на сопзЬ очевидный ответ

void foo(const struct some_struct *p) 

Это предотвратит вас от изменения непосредственных членов структуры непреднамеренно. Вот что такое const.

На самом деле, ваш вопрос звучит как копия с какой-либо викторины, а const - ожидаемый ответ.

2

В общем, когда речь идет о простых оптимизаций, как то, что вы описали, часто предпочтительно использовать pointer-to-struct, а не пропускании struct себя, как переход в целом struct означает больше накладных расходов из дополнительных данных, которые копируются на стек вызовов.

В приведенном ниже примере является довольно распространенным подходом:

#include <errno.h> 

typedef struct myStruct { 
    int i; 
    char c; 
} myStruct_t; 


int myFunc(myStruct_t* pStruct) { 
    if (!pStruct) { 
     return EINVAL; 
    } 

    // Do some stuff 

    return 0; 
} 

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

int myFunc(const myStruct_t* pStruct) 

Вы также выиграют от чтения на "const correctness".

+0

Как этот адрес представляет собой нежелательный побочный эффект, который вызываемая функция может изменять элементы_? – ryyker

+0

@rykker Hit "submit" слишком рано. Обновлено. – DevNull

+1

Видел, что сразу после того, как я ударил submit. +1 :) – ryyker

0

Очень распространенная идиома, особенно в системном коде стиля unix/posix, заключается в том, чтобы вызывающий объект выделял структуру и передавал указатель на эту структуру через вызов функции.

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

Это обеспечивает пару удобных вещей. Он избегает копирования возможной большой структуры, а также позволяет заполнителю заполнить некоторые поля и вызываемый, чтобы заполнить другие (давая эффективное общее пространство для связи).

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

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

+1

Ты взял меня на борт до последнего абзаца. Он никогда не должен сводиться к тому, чтобы потерять следы того, кому принадлежит блок объектов/блоков памяти и как он был выделен. Современные IDE и инструменты делают это не проблемой. – DevNull

+0

Вы, конечно, не должны терять из виду, кому принадлежит куча памяти. Легкость, с которой вы можете это сделать, меняется. Имейте в виду, что мы говорим о C здесь, а не C++. C++ делает выделение памяти совершенно другой. –

+0

Я согласен, что они разные, я всегда находил, что C легче отслеживать память, чем C++. В C он очень вырезанный и сухой. В C++, если вы не придерживаетесь учебника «правило из трех» и т. Д., Нужно отслеживать нюансы между конструкторами, конструкторами копирования, конструкторами присваивания, виртуальными деструкторами и т. Д. – DevNull

Смежные вопросы