简体   繁体   English

将参数传递给 C 中的结构

[英]Passing argument to a struct in C

I want to create the following struct.我想创建以下结构。

struct student
{
    char name[n+1];
    int length = n; 
};

Where n is a specific integer.其中 n 是特定整数。 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.所以我想要基于长度的不同结构。

You can use a flexible array member:您可以使用灵活的数组成员:

struct student {
  int length;
  char name[];
};

The struct is allocated and initialized for length n with:该结构被分配和初始化为长度n

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.不再使用时,请记住在s上调用free

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.最好使用 tstanisl 的答案中的解决方案。

You could use the C preprocessor to get different kinds of student structs with name arrays of different sizes.您可以使用 C 预处理器来获取具有不同大小名称数组的不同类型的学生结构。 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].但是,这些将是不同的结构类型,因此具有 char name[20 + 1] 的 student20 的类型与具有 char name[30 + 1] 的 student30 的类型相关。

#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):请注意预处理器对此做了什么(为了清楚起见,我在此处删除了 #includes):

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@

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM