在将变量传递给函数之前,用C声明变量是否更好?

在将变量传递给函数之前,用C声明变量是否更好?,c,struct,constructor,C,Struct,Constructor,还是没关系 我正在学习C语言并开始掌握结构。我试图通过将字符串值传递给一个方法,创建一个新的struct对象,并从函数返回它来模拟C中的一个基本“构造函数”方法。我意识到有几种可行的方法: 直接创建struct对象,无需卸载到方法 声明我的struct对象的所有成员变量,然后将其传递给“构造函数”方法 将要填充对象的值直接传递到“构造函数”方法中,并将结果存储在struct对象中 在一行中使用我的“构造函数”方法创建并使用struct对象,而不存储它 这是我的代码,你会明白我的意思: #incl

还是没关系

我正在学习C语言并开始掌握结构。我试图通过将字符串值传递给一个方法,创建一个新的struct对象,并从函数返回它来模拟C中的一个基本“构造函数”方法。我意识到有几种可行的方法:

  • 直接创建struct对象,无需卸载到方法
  • 声明我的struct对象的所有成员变量,然后将其传递给“构造函数”方法
  • 将要填充对象的值直接传递到“构造函数”方法中,并将结果存储在struct对象中
  • 在一行中使用我的“构造函数”方法创建并使用struct对象,而不存储它
  • 这是我的代码,你会明白我的意思:

    #include <stdio.h>
    #include <string.h>
    
    struct Book {
        char title[50];
        char author[50];
        int pageCount;
    };
    
    void printBook(struct Book _book) {
        printf("%s by %s is %d pages long.\n", _book.title, _book.author, _book.pageCount);
    }
    
    struct Book createBook(char *title, char *author, int pageCount) {
        struct Book newBook;
        strcpy(newBook.title, title);
        strcpy(newBook.author, author);
        newBook.pageCount = pageCount;
        return newBook;
    }
    
    int main() {
        // 1. Create a struct object directly.
        struct Book hp1;
        strcpy(hp1.title, "Harry Potter and the Philosopher's Stone");
        strcpy(hp1.author, "J. K. Rowling");
        hp1.pageCount = 223;
        printBook(hp1);
        
        // 2. Declare the member variables, then pass to a 'constructor' method.
        char t2[] = "A Game of Thrones";
        char a2[] = "George R. R. Martin";
        int pc2 = 687;    
        struct Book got1 = createBook(t2, a2, pc2);
        printBook(got1);
        
        // 3. Directly pass the member data to the 'constructor' method.
        struct Book ag = createBook("American Gods", "Neil Gaiman", 465);
        printBook(ag);
        
        // 4. Create a new object instance without storing it.
        printBook(createBook("Coraline", "Neil Gaiman", 186));
        return 0;
    }
    
    #包括
    #包括
    结构书{
    字符标题[50];
    char作者[50];
    整数页计数;
    };
    作废打印本(结构本){
    printf(“%s by%s是%d页长。\n”、\u book.title、\u book.author、\u book.pageCount);
    }
    struct Book createBook(字符*标题,字符*作者,整数页数){
    结构书新书;
    strcpy(newBook.title,title);
    strcpy(newBook.author,author);
    newBook.pageCount=页面计数;
    归还新书;
    }
    int main(){
    //1.直接创建一个struct对象。
    结构书hp1;
    strcpy(hp1.title,“哈利波特与魔法石”);
    strcpy(hp1.1作者,“J.K.罗琳”);
    hp1.pageCount=223;
    印刷本(hp1);
    //2.声明成员变量,然后传递给“构造函数”方法。
    char t2[]=“权力的游戏”;
    字符a2[]=“乔治·R·R·马丁”;
    int pc2=687;
    结构书got1=createBook(t2、a2、pc2);
    印刷本(got1);
    //3.直接将成员数据传递给“构造函数”方法。
    struct Book ag=createBook(“美国众神”,“尼尔·盖曼”,465);
    印刷书籍(ag);
    //4.创建一个新的对象实例而不存储它。
    印刷书(createBook(“Coraline”,“Neil Gaiman”,186));
    返回0;
    }
    

    我的问题是,这些不同方法的优缺点是什么?我理解,如果您想重新使用对象,方法4显然是不明智的,但它是否适合一次性使用?如果不先将字符串值存储在变量(方法3)中而将其传递给函数,是否存在任何隐藏成本,或者这总是比先存储字符串(方法2)更有效?

    您应该注意,如果传递长度超过50字节的字符串,此函数将导致未定义的行为

    在这种情况下,您应该使用
    strncpy
    ,并确保
    0字节
    位于数组的末尾

    struct Book createBook(char *title, char *author, int pageCount)
    {
        struct Book newBook;
        strncpy(newBook.title, title, sizeof(title));
        strncpy(newBook.author, author, sizeof(author));
        newBook.title[49] = 0;   // Truncate the string if it was too long
        newBook.author[49] = 0;
        newBook.pageCount = pageCount;
        return newBook;
    }
    
    案例1并不是一个真正的“构造函数”,因为您只需在需要的地方初始化它

    案例2是在浪费堆栈空间,因为您在堆栈上创建了一个数据副本,然后将其传递到堆栈上创建另一个副本,然后将其传递回去,这也将在堆栈上创建一个副本。之后,您的结构中已经有了这些值,所以我将引用那些插入的变量,它们不再需要了

    案例3+4基本相同,是最好的方法。如果您不再需要本地对象,只是为了调用该方法,那么您不需要保留副本

    你应该意识到,特别是对于较大的结构,用值复制对象是非常无效的,所以你可能需要考虑动态分配对象并在完成时释放它。因为

    C
    不像
    C++
    那样提供析构函数机制,所以您必须自己做


    但是,您实现“构造函数”的方式不需要任何释放。

    方法1很尴尬,您可以自己看到。方法2毫无意义,而是使用方法3。方法4实际上取决于您的用例,如果您不需要存储它,它是完全有效的,但另一方面,这本书将如何销毁?最好的可能是方法3,它显然是最简单和最可读的版本,但无论如何,您可能需要调用
    deleteBook(ag)
    ,一旦您完成这本书,取决于
    createBook
    的功能(比如分配内存)。谢谢,我不知道您也需要删除结构。从谷歌搜索中,删除[bookObject]应该是一行
    ,正确?没有代码>删除[BooObj] ] /Cuth>不是C(NOR C++ + BTW)。对于删除,您需要编写自己的函数,但在您的情况下,不需要使用deleter函数,因为
    createBook
    不分配任何内存(或其他需要撤消的内容),谢谢!如果字符串长度超过50个字节,您能否澄清“未定义行为”是什么以及为什么会发生?C字符数组不能容纳超过50个字节吗?我也很困惑,因为你说的是字节,但你已经将字符数组的第50个字符设置为空字符(至少,我认为是这样)。否则我接受了答案,因为它完美地回答了我的主要问题,我只是不理解这些细节:)它不能容纳超过50个字符,因为你在声明中说数组只能容纳50个字符
    chartitle[50]。由于c字符串需要一个
    0字节
    ,它只能有49个字符,因为它也需要一个字符。如果你现在复制一个200个字符的字符串,你的堆栈会被覆盖,程序可能会崩溃。啊。。。我真是太愚蠢了,我忘了我用显式边界实例化了我的数组。你的回答现在很有道理——给我一点时间把鸡蛋从我脸上拿开:)