Чи є якісь мінуси для передачі структур за значенням у C, а не передачі вказівника?
Якщо структура є великою, очевидно, є виконуючий аспект копіювання безлічі даних, але для меншої структури вона в основному повинна бути такою ж, як передача декількох значень функції.
Це може бути навіть цікавіше, коли вони використовуються як повернені значення. C має лише одиничні значення повернення від функцій, але вам часто потрібно кілька. Таким простим рішенням є скласти їх у структуру та повернути це.
Чи є причини для цього чи проти?
Оскільки може бути не очевидно для всіх, про що я тут говорю, я наведу простий приклад.
Якщо ви програмуєте на C, ви рано чи пізно почнете писати функції, які виглядають приблизно так:
void examine_data(const char *ptr, size_t len)
{
...
}
char *p = ...;
size_t l = ...;
examine_data(p, l);
Це не проблема. Єдине питання полягає в тому, що ви повинні погодитись зі своїм колегою, в якому параметри порядку повинні бути, щоб ви використовували однаковий режим у всіх функціях.
Але що відбувається, коли ви хочете повернути той самий вид інформації? Зазвичай ви отримуєте щось подібне:
char *get_data(size_t *len);
{
...
*len = ...datalen...;
return ...data...;
}
size_t len;
char *p = get_data(&len);
Це прекрасно працює, але набагато проблематичніше. Повернене значення - це повернене значення, за винятком того, що в цій реалізації воно не є. Немає способу сказати з вищесказаного, що функції get_data заборонено дивитися на те, на що вказує len. І ніщо не змушує компілятора перевірити, чи значення насправді повертається через цей покажчик. Тож у наступному місяці, коли хтось інший модифікує код, не розуміючи його належним чином (тому що він не прочитав документацію?), Він розбивається, не помічаючи когось, або він починає вибиватися випадковим чином.
Отже, рішення, яке я пропоную, - це проста структура
struct blob { char *ptr; size_t len; }
Приклади можна переписати так:
void examine_data(const struct blob data)
{
... use data.tr and data.len ...
}
struct blob = { .ptr = ..., .len = ... };
examine_data(blob);
struct blob get_data(void);
{
...
return (struct blob){ .ptr = ...data..., .len = ...len... };
}
struct blob data = get_data();
З якоїсь причини я думаю, що більшість людей інстинктивно змусили exam_data взяти покажчик на структурну крапку, але я не розумію, чому. Він все одно отримує вказівник і ціле число, просто набагато зрозуміліше, що вони йдуть разом. І у випадку get_data неможливо зіпсувати так, як я описав раніше, оскільки немає вхідного значення для довжини, і повинна бути повернута довжина.
gettimeofday
), використовують замість цього покажчики, і люди беруть це як приклад.
void examine data(const struct blob)
невірно.