Что означает этот указатель определения структуры типа (в C)?
В главе 6 К&Р декларация упоминается следующим образом:
struct{
int len;
char *str;
} *p;
Я не мог понять, на какую структуру указывает этот указатель p, и если такое определение указателя вообще допустимо, потому что во всех других примерах, приведенных в книге, и тех, которые я видел в противном случае, при определении указателя на структуру необходимо упомянуть имя структуры, то есть определяемый тип. Например,
struct example{
int a;
...
}s1;
А затем,
struct example *ptr = &s1;
Итак, упоминается, что ptr является указание на тип struct пример, а не просто struct.
Также особый интерес представляло следующее:
*р->ул. выбирает, что стр точек; *р->ул.++ увеличивает str после обращения к тому, на что он указывает (так же, как *s++);
Я не мог проследить, что такое p в первую очередь, следовательно, не инкремент и разыменование, а также.
Что здесь происходит?
Заранее спасибо!
P.S. Я здесь новичок, поэтому любая обратная связь по формату вопрос также будет оценен.
4 ответа:
Ключевое слово
Первый оператор, на который вы смотрите, объявляет структуру с двумя полями, но не называет ее. Это называется анонимной структурой. Декларация, однако, предусматривает следующее: указатель такого типа. Одним из возможных вариантов использования такого объявления является создание заголовка для внешней библиотеки, возможно, даже не написанной на языке C. В этом случае тип структуры может быть непрозрачным или неполным, и вам просто нужно иметь удобную ссылку на некоторые ее части. Создание анонимной структуры не позволяет вам легко выделить ее самостоятельно, но позволяет взаимодействовать с ней через указатель.struct
работает как расширенная версияtypedef
, за исключением того, что вы создаете сложный пользовательский тип (называемый структурой) вместо псевдонима существующего типа. Если у вас есть только одна вещь, которая должна использовать объявленный тип, вам не нужно предоставлять явное имя для типа.Чаще всего вы будете смотрите эту нотацию, используемую в сочетании с именованными или, по крайней мере, псевдонимными структурами. Второе утверждение может быть переписано как
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 ) );
Для этой простой программы имя структуры не требуется, потому что ни объявление объекта типа структуры не присутствует и не требуется в программе.
Так что вы не можете объявите объект типа structure, но в этом случае он не требуется.
В соответствии со стандартом C структура или объединение объявляются как
struct-or-union-specifier: struct-or-union identifieropt { struct-declaration-list } struct-or-union identifierВидно, что идентификатор является необязательным, если существует структура-объявление-список. Таким образом, безымянная структура может использоваться в качестве спецификатора типа.
Еще один пример с использованием перечислений. Перечислители можно объявлять без объявления типа перечисления. Например
enum { EXIT_SUCCESS = 0, EXIT_FAILURE = -1 };
Вы можете использовать перечислители, которые иметь тип
int
без объявления объекта перечислительного типа, если в программе нет такого требования.
Также другое использование (анонимных структур) было бы использовать их внутри союзов или других структур, которые в основном ограничивают использование этой структуры конкретным родительским союзом или структурой, а не чем-либо еще, что весьма полезно с точки зрения программиста, потому что, глядя на такой код, он предоставляет нам информацию о том, что он используется локально в контексте структуры или союза внутри него. - и ничего больше. (также избавляет нас от именования).
Также если вы используя эту анонимную структуру, вы не сможете выделить ни одного ее экземпляра, кроме уже существующего.
Пример: - (комментарий Старка: как его использовать?)
struct { int a; int b; } p; scanf("%d",&p.a);
Если вам нужно специальное, одноразовое определение структуры (или объединения), которое не будет полезно вне области, в которой оно было объявлено, вы будете использовать то, что называется анонимными или неназванными структурами и объединениями. Это избавляет вас от необходимости объявлять структуру перед ее использованием и, в случае сложных типов, объявлять внутренние типы, такие как здесь.