Использование стрелки (->) в C

В настоящее время я изучаю C, читая книгу хорошего новичка «Teach Yourself C через 21 день» (я уже изучил Java и C #, поэтому я продвигаюсь намного быстрее). Я читал главу о указателях, и оператор -> (стрелка) подошел без объяснений. Я думаю, что он используется для вызова членов и функций (например, эквивалент оператора. (Dot), но для указателей вместо членов). Но я не совсем уверен. Могу ли я получить объяснение и образец кода?

foo->bar эквивалентно (*foo).bar , т. е. он получает член, называемый bar из структуры, на которую указывает foo .

Да это оно.

Это просто точечная версия, когда вы хотите получить доступ к элементам struct / class, который является указателем вместо ссылки.

 struct foo { int x; float y; }; struct foo var; struct foo* pvar; var.x = 5; (&var)->y = 14.3; pvar->y = 22.4; (*pvar).x = 6; 

Это оно!

a->b просто коротко для (*a).b всякий раз (тот же для функций: a->b() является коротким для (*a).b() ).

foo->bar является только сокращением для (*foo).bar . Вот и все.

 struct Node { int i; int j; }; struct Node a, *p = &a; 

Здесь для доступа к значениям i и j мы можем использовать переменную a и указатель p следующим образом: ai , (*p).i и p->i все одинаковы.

Здесь . «Прямой выбор» и -> «Непрямой селектор».

Я бы просто добавил к ответам «почему?».

. является стандартным оператором доступа к члену, который имеет более высокий приоритет, чем оператор указателя * .

Когда вы пытаетесь получить доступ к внутренним структурам, и вы написали их как *foo.bar тогда компилятор думал бы, что хочет элемент «bar» из «foo» (который является адресом в памяти) и, очевидно, что простой адрес не имеет любых членов.

Таким образом, вам нужно попросить компилятор сначала разыменовать whith (*foo) а затем получить доступ к элементу-члену: (*foo).bar , который немного (*foo).bar писать, поэтому хорошие люди придумали сокращенную версию: foo->bar который является своего рода доступом к членству оператором указателя.

Я должен был внести небольшое изменение в программу Джека, чтобы заставить ее работать. После объявления указателя struct pvar укажите его на адрес var. Я нашел это решение на стр. 242 программирования Стивена Кочана в C.

 #include  int main() { struct foo { int x; float y; }; struct foo var; struct foo* pvar; pvar = &var; var.x = 5; (&var)->y = 14.3; printf("%i - %.02f\n", var.x, (&var)->y); pvar->x = 6; pvar->y = 22.4; printf("%i - %.02f\n", pvar->x, pvar->y); return 0; } 

Запустите это в vim со следующей командой:

 :!gcc -o var var.c && ./var 

Вывод:

 5 - 14.30 6 - 22.40 
 #include int main() { struct foo { int x; float y; } var1; struct foo var; struct foo* pvar; pvar = &var1; /* if pvar = &var; it directly takes values stored in var, and if give new > values like pvar->x = 6; pvar->y = 22.4; it modifies the values of var object..so better to give new reference. */ var.x = 5; (&var)->y = 14.3; printf("%i - %.02f\n", var.x, (&var)->y); pvar->x = 6; pvar->y = 22.4; printf("%i - %.02f\n", pvar->x, pvar->y); return 0; } 

Оператор -> делает код более читаемым, чем оператор * в некоторых ситуациях.

Например: (цитируется в проекте EDK II )

 typedef EFI_STATUS (EFIAPI *EFI_BLOCK_READ)( IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, OUT VOID *Buffer ); struct _EFI_BLOCK_IO_PROTOCOL { /// /// The revision to which the block IO interface adheres. All future /// revisions must be backwards compatible. If a future version is not /// back wards compatible, it is not the same GUID. /// UINT64 Revision; /// /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device. /// EFI_BLOCK_IO_MEDIA *Media; EFI_BLOCK_RESET Reset; EFI_BLOCK_READ ReadBlocks; EFI_BLOCK_WRITE WriteBlocks; EFI_BLOCK_FLUSH FlushBlocks; }; 

Структура _EFI_BLOCK_IO_PROTOCOL содержит 4 элемента указателя функций.

Предположим, что у вас есть переменная struct _EFI_BLOCK_IO_PROTOCOL * pStruct , и вы хотите использовать старый добрый оператор * чтобы вызвать его указатель на функцию-член. Вы получите код следующим образом:

(*pStruct).ReadBlocks(...arguments...)

Но с помощью оператора -> вы можете написать вот так:

pStruct->ReadBlocks(...arguments...) .

Что выглядит лучше?

Dot – это оператор разыменования и используется для связывания структурной переменной для конкретной записи структуры. Например:

 struct student { int s.no; Char name []; int age; } s1,s2; main() { s1.name; s2.name; } 

Таким образом, мы можем использовать оператор точки для доступа к структурной переменной

 #include struct examp{ int number; }; struct examp a,*b=&a;`enter code here` main() { a.number=5; /* a.number,b->number,(*b).number produces same output. b->number is mostly used in linked list*/ printf("%d \n %d \n %d",a.number,b->number,(*b).number); } 

выход 5 5 5

  • Что такое тип данных uintptr_t
  • Разница между char * str = "STRING" и char str = "STRING"?
  • Инициализация указателя в отдельной функции в C
  • Что такое C-указатель, если не адрес памяти?
  • Являются ли a, & a, a, a , & a и & a одинаковыми указателями?
  • Что такое имя массива в c?
  • Причина, почему бы не иметь макрос DELETE для C ++
  • Как выровнять указатель в C
  • Как печатать переменные адреса в C?
  • Псевдонимы, вызываемые разыменованием, нарушат правила строгого сглаживания
  • Почему существует оператор стрелки (->) в C?
  • Давайте будем гением компьютера.