I want to create the following struct.
struct student
{
char name[n 1];
int length = n;
};
Where n is a specific integer. Is it possible to pass an argument to a struct or another solution to achieve something like this? Maybe pointers. So I want different structs based on length.
CodePudding user response:
You can use a flexible array member:
struct student {
int length;
char name[];
};
The struct is allocated and initialized for length n
with:
struct student *s = malloc(sizeof *s n 1);
s->length = n;
// initialize s->name
strcpy(s->name, the_name_of_n_chars);
Remember to call free
on s
when it is no longer used.
CodePudding user response:
Here is a way to have something like parameterized types, but I would not recommend that you do this! As you can see in the example below, it may not give you what you want and no extra safety. Better use the solution from tstanisl's answer.
You could use the C preprocessor to get different kinds of student structs with name arrays of different sizes. However, these will be distinct struct types, so the type of a student20 with char name[20 1] is related to the type of a student30 with char name[30 1].
#include <string.h>
#include <stdio.h>
#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("%d\n", student3.length);
printf("%d\n", student2.length);
STUDENT(1) impossibleStudent = INIT_STUDENT("Walter");
printf("%d %s\n", impossibleStudent.length, impossibleStudent.name);
}
Note what the preprocessor makes out of this (I removed the #includes here for clarity):
C:\cygwin64\tmp\preproc>gcc -E student.c
# 1 "student.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 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("%d\n", student3.length);
printf("%d\n", student2.length);
struct student1 impossibleStudent = { "Walter", strlen("Walter") };
printf("%d %s\n", impossibleStudent.length, impossibleStudent.name);
}
Here is what happens when I compile and run it:
C:\cygwin64\tmp\preproc>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:\cygwin64\tmp\preproc>a.exe
0
5
6 Wa@
CodePudding user response:
Here is another implementation, apart from the other answers.
#include <string.h>
#include <stdlib.h>
struct student
{
char *name;
int length;
};
struct student *
alloc_student(char *name)
{
struct student *new;
new = malloc(sizeof(struct student));
if (new)
{
new->name = malloc(strlen(name) 1);
if (new->name)
{
new->length = strlen(name);
strcpy(new->name, name);
}
else
{
free(new);
new=NULL;
}
return new;
}
void
dealloc_student(struct student *s)
{
free(s->name);
free(s);
}
int
main(void)
{
struct student *s0;
s0 = alloc_student("John");
if (s0) dealloc_student(s0);
return 0;
}