Инициализировать постоянный указатель на массив в той же структуре - PullRequest
2 голосов
/ 16 декабря 2010
typedef struct {
    char a[100];
    char const *secondHalfOfA;
}
//Can i set { secondHalfOfA = a[49]; } somehow?

Ответы [ 4 ]

3 голосов
/ 16 декабря 2010

Конечно, вы можете.

typedef struct {
    char a[100];
    char const *const secondHalfOfA;
} toto;
#define TOTO_INITIALIZER(NAME) { .secondHalfOfA = &((NAME).a[49]) }

static toto A = TOTO_INITIALIZER(A);

Использование таких инициализаторов последовательно имеет дополнительный плюс, что он инициализирует ваш массив также всеми 0.

Это для C99 с обозначенныминициализаторы.Если у вас есть только исторический C, вы могли бы сделать что-то вроде

#define TOTO_INITIALIZER(NAME) { { 0 }, &((NAME).a[49]) }

Редактировать: Видя ваш комментарий к другому ответу, я полагаю, что вы набрали const в вашем типе неправильнобоковая сторона.Но реальная инициализация C работает очень хорошо и для этого случая.

2 голосов
/ 16 декабря 2010

Вы не можете автоматически инициализировать указатель на середину объекта.

Однако вы можете делать вид, что перекрывающиеся объекты. Это не красиво, хотя: -)

#include <stdio.h>
#include <string.h>

struct twoparts {
  union {
    char a[20];
    struct {
      char dummy[10];
      char b[10];
    } s;
  } u;
};

int main(void) {
  struct twoparts x;
  strcpy(x.u.a, "1234567890123456789");
  printf("second part: %s\n", x.u.s.b);
  return 0;
}
1 голос
/ 16 декабря 2010

Это Пабло сказал , вы не можете сделать это с инициализатором.Вы можете сделать это достаточно легко после инициализации, но это должно происходить каждый раз:

// Definition (once)
typedef struct {
    char a[100];
    char const *secondHalfOfA;
} TYPENAME;

// Use (each time)
TYPENAME t;
t.secondHalfOfA = &t.a[49];

// Or
TYPENAME *pt;
pt = malloc(sizeof(*pt));
pt->secondHalfOfA = &pt->a[49];

Именно по таким причинам у нас есть объектно-ориентированные языки, такие как C ++ (и Java и ...) и связанные с ними конструкторы , чтобы мы могли надежно создавать структуры с пользовательскими инициализациями.


Демонстрационная программа:

#include <stdio.h>

// Definition (once)
typedef struct {
    char a[100];
    char const *secondHalfOfA;
} TYPENAME;

int main(int argc, char* argv[])
{
    // Use of the type (need to initialize it each time)
    TYPENAME t;
    t.secondHalfOfA = &t.a[49];

    // Example actual use of the array
    t.a[49] = 'A';
    printf("%c\n", *t.secondHalfOfA); // Prints A

    // Uncommenting the below causes a compiler error:
    // "error: assignment of read-only location ‘*t.secondHalfOfA’"
    // (That's gcc's wording; your compiler will say something similar)
    //*t.secondHalfOfA = 'B';
    //printf("%c\n", *t.secondHalfOfA);

    return 0;
}

Компиляция и вывод с использованием gcc:

$ gcc -Wall temp.c
$ ./a.out
A
1 голос
/ 16 декабря 2010

Нет.Вы не можете сделать это за typedef.Помните: с ключевым словом typedef вы определяете типы данных, а не переменные.

В C ++ вы можете сделать это в конструкторе по умолчанию.Но в Си нет способа сделать это.

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