Возможные побочные эффекты делать typedef для структуры в массив один элемент с
Я наткнулся на этот код.
typedef __mpz_struct MP_INT;
typedef __mpz_struct mpz_t[1];
Здесь структура __mpz_struct
- это структура, которая типизирована в массив одного элемента. Я понимаю, что это трюк для передачи по ссылке в C. Затем mpz_t
был использован в качестве типа для объявления переменных и передачи их в функцию в качестве параметров. Кроме того, был еще один комментарий
/*
MP_INT*, MP_RAT* and MP_FLOAT* are used because they don't have side-effects
of single-element arrays mp*_t
*/
О каких побочных эффектах идет речь?
4 ответа:
Передавая массив в функцию, пусть массив распадается на указатель на его 1-й элемент.
Такого же эффекта можно достичь, применив оператор Address-Of&
к простой переменной того же типа, что и элементы массива.Примеры:
struct S { int i; float f; };
Это
void set_S(struct S * ps) { ps->i = 40; ps->f = 2.; }
Эквивалентно
void set_S(struct S ps[1]) { ps->i = 40; ps->f = 2.; }
Эквивалентно
void set_S(struct S * ps) { ps[0].i = 40; ps[0].f = 2.; }
Эквивалентно
void set_S(struct S ps[1]) { ps[0].i = 40; ps[0].f = 2.; }
Одноэлементный подход к массиву:
typedef struct S Array_of_S_with_size_1[1]; int main(void) { Array_of_S_with_size_1 array_of_S_with_size_1; array_of_S_with_size_1[0].i = 0; array_of_S_with_size_1[0].f = 0.; set_S(array_of_S_with_size_1); ... }
Вышеуказанное
main()
обеспечивает те же функции, что и следующие:int main(void) { struct S s; s.i = 0; s.f = 0.; set_S(&s); ... }
Я не вижу никакого усиления, используя подход " одноэлементный массив". Выражение может быть, если
&
-клавиша сломана на одной клавиатуре ... ;- )
Я вижу двух частей на ваш вопрос. Первую часть, как typedef работает для передачи аргументов в функции, лучше проиллюстрировать на примере. Без него мне придется немного догадаться.
В объявлениях функций C параметр массива эквивалентен указателю. Вот почему вы видите (например) эквивалентно для основной функции,
int main(int argc, char **argv)
И
int main(int argc, char *argv[])
Аналогично, если функция в вашей программе будет объявлена
int func(__mpz_struct *arg)
Это было бы эквивалентно
int func(__mpz_struct arg[])
И, следовательно, к
int func(mpz_t arg)
Кроме того, на вызывающей стороне, если у вас есть переменная типа mpz_t, следовательно, массив, и вы передаете ее функции," распад указателя "вступает в силу: в выражении, если вы используете (имя) массива, он" распадается " в указатель на его первый элемент. Таким образом, вы можете вызвать функцию:
mpz_t value; func(value);
Конечно, чтобы модифицировать эти объекты mpz_t вне функций API, вы все равно должны знать об их истинном значении. природа.
Побочные эффекты, о которых вы упомянули, я также должен был бы догадаться о них. Возможно, это означает, что вы должны осознавать, что работаете с указателями внутри функций. Было бы лучше сделать это явным, используя синтаксис указателя.
Вы можете назначить MP_INT другому, но вы не можете назначить mpz_t другому, так как назначение не определено для массивов. Если вы не хотите, чтобы ваши клиенты назначали переменные, отличные от ваших методов (которые могут выполнять управление памятью и прочее), это трюк для вас.
Посмотрите на этот пример кода
typedef char type24[3];
То же, что и ваш, но хорошо известный тип данных 'char' вместо вашего типа struct
__mpz_struct
.Выше типа def означает, что я использую выше typedef для представления char[3].
Итак, в вашем примере кода,
typedef __mpz_struct mpz_t[1];
mpz_t
должно быть__mpz_struct
типа.