Что означает этот указатель определения структуры типа (в C)?
В главе 6 K&R декларация упоминается следующим образом:
struct{
int len;
char *str;
} *p;
Я не мог понять, на какую структуру указывает указатель p и является ли такое определение указателя действительным, потому что во всех других примерах, приведенных в книге, и в тех, которые я видел иначе, при определении указателя на структуру, имя структура, то есть определяемый тип должен быть упомянут. Например,
struct example{
int a;
...
}s1;
а потом,
struct example *ptr = &s1;
Итак, упоминается, что ptr указывает на пример структуры типа, а не только на структуру.
Также особый интерес представляло это:
* p-> str извлекает все, на что указывает str; *p->str++ увеличивает str после доступа к тому, на что он указывает (точно так же как *s++);
Я не мог понять, что p в первую очередь, следовательно, не приращение и разыменование также.
Что здесь происходит?
Заранее спасибо!
PS Я новичок здесь, поэтому любые отзывы о формате вопроса также будут оценены.
4 ответа
struct
ключевое слово работает как расширенная версия typedef
за исключением того, что вы создаете сложный пользовательский тип (называемый структурой) вместо того, чтобы создавать псевдонимы для существующего типа. Если у вас есть только одна вещь, которая должна использовать объявленный тип, вам не нужно указывать явное имя для типа.
Первый оператор, который вы просматриваете, объявляет структуру с двумя полями, но не называет ее. Это называется анонимной структурой. Однако объявление предоставляет указатель этого типа.
Один из возможных вариантов использования для такого объявления - когда вы создаете заголовок для внешней библиотеки, возможно, такой, которая даже не написана на C. В этом случае тип структуры может быть непрозрачным или неполным, и вам просто нужно иметь удобную ссылку на некоторые его части. Анонимная структура не позволяет вам легко размещать ее самостоятельно, но позволяет вам взаимодействовать с ней через указатель.
Чаще всего вы увидите, что это обозначение используется в сочетании с именованными или хотя бы псевдонимными структурами. Второе утверждение может быть переписано как
struct example { ... } s1, *ptr;
В таком случае, struct example *ptr = &s1;
было бы просто ptr = &s1;
,
Еще более распространенным явлением является использование анонимных структур с typedef
создать собственные имена типов, которые не включают struct
ключевое слово. Ваш второй пример может быть переписан как
typedef struct { ... } example, *pexample;
example s1;
pexample ptr; // alternatively example *ptr;
ptr = &s1;
Обратите внимание, что тип s1
является example
и не struct example
в этом случае.
Для начала рассмотрим следующую простую программу
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
struct {
int len;
char *str;
} *p;
p = malloc( sizeof( *p ) );
p->str = "Hello Nihal Jain";
p->len = strlen( p->str );
while ( *p->str ) putchar( *p->str++ );
putchar( '\n' );
free( p );
return 0;
}
Его вывод
Hello Nihal Jain
Так что в этой декларации
struct {
int len;
char *str;
} *p;
там объявлен указатель типа безымянной структуры. Сам указатель не инициализирован. Вы могли бы написать, например,
struct {
int len;
char *str;
} *p = malloc( sizeof( *p ) );
Для этой простой программы имя структуры не требуется, потому что ни объявление объекта типа структуры не присутствует или не требуется в программе.
Таким образом, вы не можете объявить объект типа структуры, но это не требуется в этом случае.
Согласно стандарту C структура или объединение объявляются как
структура или всесоюзные спецификаторы: идентификатор структуры или объединенияopt {список-объявления-структуры} идентификатор структуры или объединения
Видно, что идентификатор является необязательным, если существует список struct-объявление. Таким образом, безымянная структура может использоваться как спецификатор типа.
Еще один пример с использованием перечислений. Вы можете объявить перечислители без объявления типа перечисления. Например
enum { EXIT_SUCCESS = 0, EXIT_FAILURE = -1 };
Вы можете использовать перечислители, которые имеют тип int
без объявления объекта типа перечисления, если в программе нет такого требования.
Также другим использованием (анонимных структур) будет использование их внутри союзов или других структур, которые в основном ограничивают использование этой структуры этим конкретным родительским объединением или структурой, а не чем-то еще, что весьма полезно с точки зрения программиста, поскольку взгляд на Подобный код предоставляет нам информацию о том, что он используется локально в контексте структуры или объединения внутри него - не более того. (также спасает нас от именования).
Также, если вы используете эту анонимную структуру, вы не сможете выделить один ее экземпляр, отличный от того, который уже существует.
Пример:-(комментарий Старка: как его использовать?)
struct {
int a;
int b;
} p;
scanf("%d",&p.a);
Если вам нужно специальное одноразовое определение структуры (или объединения), которая не будет полезна вне области, в которой она была объявлена, вы должны использовать так называемые анонимные или неназванные структуры и объединения. Это избавляет вас от необходимости объявлять структуру перед ее использованием и, в случае сложных типов, объявлять внутренние типы, например, здесь.