Подтвердить что ты не робот

Что означает этот указатель определения структуры типа (в C)?

В K & R Chapter 6 выражение упоминается следующим образом:

struct{
    int len;
    char *str;
} *p;

Я не мог понять, к какой структуре относится этот указатель p, и если такое определение указателя даже справедливо, потому что во всех других примерах, приведенных в книге, и тех, которые я видел иначе, при определении указателя на структуру, необходимо указать название структуры, то есть тип, который определяется. Например,

struct example{
    int a;
    ...
}s1;

а затем

struct example *ptr = &s1;

поэтому упоминается, что ptr указывает на пример структуры типа, а не только на структуру.

Кроме того, особенно интересным было следующее:

* p- > str извлекает любые str-точки; * P- > ул ++ увеличивает str после доступа к тому, на что он указывает (точно так же, как * s ++);

Я не мог следить за тем, что p в первую очередь, следовательно, а не приростом и разыменованием.

Что здесь происходит?

Спасибо заранее!

P.S. Я новичок здесь, поэтому любые отзывы о формате вопроса также будут оценены.

4b9b3361

Ответ 1

Ключевое слово 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 в этом случае.

Ответ 2

Для начала рассмотрим следующую простую программу

#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 Standard объявляются как

struct-or-union-specifier:
    struct-or-union identifieropt { struct-declaration-list }
    struct-or-union identifier

Видно, что идентификатор является необязательным, если существует список struct-declaration-list. Таким образом, неназванная структура может использоваться как спецификатор типа.

Еще один пример использования перечислений. Вы можете объявлять счетчики без объявления типа перечисления. Например

enum { EXIT_SUCCESS = 0, EXIT_FAILURE = -1 }; 

Вы можете использовать перечисления, которые имеют тип int, не объявляя объект типа перечисления, если в программе нет такого требования.

Ответ 3

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


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

Пример:-( громкий комментарий: как его использовать?)

struct {
  int a;
  int b;
} p;

scanf("%d",&p.a);

Ответ 4

Если вам понадобилось одноразовое одноразовое определение структуры (или объединения), которое не будет полезно вне области, в которой оно было объявлено, вы должны использовать то, что называется анонимные или неназванные структуры и объединения. Это избавит вас от необходимости объявлять структуру до ее использования, а в случае сложных типов - объявлять внутренние типы, такие как здесь.