Передача аргумента структуре в C

#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. Интересный….