#arrays #c #pointers
Вопрос:
Я хочу создать следующую структуру.
struct student { char name[n 1]; int length = n; };
Где n — определенное целое число. Можно ли передать аргумент структуре или другому решению для достижения чего-то подобного? Может быть, указатели. Поэтому мне нужны разные структуры, основанные на длине.
Комментарии:
1. в C размер массива должен быть фиксированным. Тогда ответ будет отрицательным. Для этого вам необходимо динамически создать массив в куче.
2. @CroCo «размер массива должен быть фиксированным». С помощью гибкого члена массива и других тактик «необходимо динамически создавать массив в куче» не является абсолютной истиной.
Ответ №1:
Вы можете использовать гибкий элемент массива:
struct student { int length; char name[]; };
Структура выделяется и инициализируется по длине n
с:
struct student *s = malloc(sizeof *s n 1); s-gt;length = n; // initialize s-gt;name strcpy(s-gt;name, the_name_of_n_chars);
Не забудьте позвонить free
s
, когда он больше не используется.
Комментарии:
1. Немного больше информации:
malloc(sizeof *s sizeof s-gt;name[0] * (n 1));
. Конечно, в данном случаеsizeof s-gt;name[0] == 1
так не нужно. Но в общем случае масштабируйте по размеру элементов FAM.
Ответ №2:
Вот еще одна реализация, помимо других ответов.
#include lt;string.hgt; #include lt;stdlib.hgt; struct student { char *name; int length; }; struct student * alloc_student(char *name) { struct student *new; new = malloc(sizeof(struct student)); if (new) { new-gt;name = malloc(strlen(name) 1); if (new-gt;name) { new-gt;length = strlen(name); strcpy(new-gt;name, name); } else { free(new); new=NULL; } return new; } void dealloc_student(struct student *s) { free(s-gt;name); free(s); } int main(void) { struct student *s0; s0 = alloc_student("John"); if (s0) dealloc_student(s0); return 0; }
Ответ №3:
Вот способ создать что-то вроде параметризованных типов, но я бы не рекомендовал вам этого делать! Как вы можете видеть в приведенном ниже примере, это может не дать вам того, что вы хотите, и не обеспечить дополнительной безопасности. Лучше используйте решение из ответа tstanisl.
Вы можете использовать препроцессор C для получения различных типов структур учащихся с массивами имен разных размеров. Однако это будут разные типы структур, поэтому тип студента 20 с именем символа[20 1] связан с типом студента 30 с именем символа[30 1].
#include lt;string.hgt; #include lt;stdio.hgt; #define DEFSTUDENT(n) struct student##n { char name[n 1]; int length; } #define STUDENT(n) struct student##n #define INIT_STUDENT(name) { name, strlen(name) } DEFSTUDENT(100) student1 = INIT_STUDENT("John"); DEFSTUDENT(20) student2 = INIT_STUDENT("James"); DEFSTUDENT(1); int main() { STUDENT(20) student3 = INIT_STUDENT(""); printf("%dn", student3.length); printf("%dn", student2.length); STUDENT(1) impossibleStudent = INIT_STUDENT("Walter"); printf("%d %sn", impossibleStudent.length, impossibleStudent.name); }
Обратите внимание, что делает из этого препроцессор (я удалил #включает здесь для ясности):
C:cygwin64tmppreprocgt;gcc -E student.c # 1 "student.c" # 1 "lt;built-ingt;" # 1 "lt;command-linegt;" # 1 "student.c" # 11 "student.c" struct student100 { char name[100 1]; int length; } student1 = { "John", strlen("John") }; struct student20 { char name[20 1]; int length; } student2 = { "James", strlen("James") }; struct student1 { char name[1 1]; int length; }; int main() { struct student20 student3 = { "", strlen("") }; printf("%dn", student3.length); printf("%dn", student2.length); struct student1 impossibleStudent = { "Walter", strlen("Walter") }; printf("%d %sn", impossibleStudent.length, impossibleStudent.name); }
Вот что происходит, когда я компилирую и запускаю его:
C:cygwin64tmppreprocgt;gcc student.c student.c: In function 'main': student.c:22:49: warning: initializer-string for array of chars is too long STUDENT(1) impossibleStudent = INIT_STUDENT("Walter"); ^ student.c:11:30: note: in definition of macro 'INIT_STUDENT' #define INIT_STUDENT(name) { name, strlen(name) } ^~~~ student.c:22:49: note: (near initialization for 'impossibleStudent.name') STUDENT(1) impossibleStudent = INIT_STUDENT("Walter"); ^ student.c:11:30: note: in definition of macro 'INIT_STUDENT' #define INIT_STUDENT(name) { name, strlen(name) } ^~~~ C:cygwin64tmppreprocgt;a.exe 0 5 6 Wa@
Комментарии:
1. Интересный….