Массив typedef против указателя typedef - PullRequest
1 голос
/ 07 августа 2020

GMP объявляет следующую структуру:

typedef struct
{
  int _mp_alloc;
  int _mp_size;
  mp_limb_t *_mp_d;
} __mpz_struct;

, а затем эти два определения типов:

typedef __mpz_struct mpz_t[1];
typedef __mpz_struct *mpz_ptr;

Какова причина этих двух отдельных (и вроде бы же) определения? В чем разница между ними?

1 Ответ

2 голосов
/ 07 августа 2020

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

Первый typedef в вашем примере позволяет объявить объект введите mpz_t, который будет одиночным _mpz_struct объектом (массив размером 1); однако, поскольку он объявлен как массив, его имя может использоваться как указатель (например, при переходе к функции, которая требует указателя на этот тип структуры).

Второй typedef - это простой указатель. Любая объявленная таким образом переменная должна иметь адрес фактической структуры, присвоенный ей, прежде чем ее можно будет использовать (разыменовать).

Последний тип позволит изменять конкретный объект, на который он указывает к, тогда как первый тип - это «фиксированный» указатель на определенный объект (или «поддельный» массив), объявленный.

У меня нет доступа к библиотеке GMP, поэтому я не могу привести пример используя это, но следующий код может иллюстрировать тонкую разницу между двумя типами:

#include <stdio.h>

typedef struct {
    int a;
    int b;
    double d;
} MyStruct;

typedef MyStruct MS_t[1];
typedef MyStruct* MS_ptr;

int main()
{
    MS_t mt;
    MS_ptr mp;
    printf("Size of type = %zu; Size of pointer = %zu\n\n", sizeof(MS_t), sizeof(MS_ptr));

    mt->a = 1; mt->b = 2; mt->d = 3.141; // Good - "mt" can be used as a pointer to first (only) element of the array.
//  mp->a = 3; mp->b = 7; mp->d = 3.141; // UNDEFINED BEHAVIOUR - mp doesn't point to anything.

    MyStruct ms1, ms2 = { 3, 8, 42.42 };
    mp = &ms1;
    mp->a = 2; mp->b = 4; mp->d = 2.718; // OK - mp now points to a valid structure (ms1)

    printf("MT: %d %d %f\n", mt->a, mt->b, mt->d);
    printf("MP: %d %d %f\n", mp->a, mp->b, mp->d);

    // Let's try to change addresses:
    mp = &ms2; // We can change what "mp" points to whenever we like
    printf("MP: %d %d %f\n", mp->a, mp->b, mp->d); // Different address -> different structure -> different data!
//  mt = &ms2; // ERROR: array type 'MS_t' (aka 'MyStruct [1]') is not assignable

    mp = mt; // We can even use "mt" as an address to assign to "mp"
    printf("MP: %d %d %f\n", mp->a, mp->b, mp->d); // This shows the 'first' data set values

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...