在将变量传递给函数之前,用C声明变量是否更好?
还是没关系 我正在学习C语言并开始掌握结构。我试图通过将字符串值传递给一个方法,创建一个新的struct对象,并从函数返回它来模拟C中的一个基本“构造函数”方法。我意识到有几种可行的方法:在将变量传递给函数之前,用C声明变量是否更好?,c,struct,constructor,C,Struct,Constructor,还是没关系 我正在学习C语言并开始掌握结构。我试图通过将字符串值传递给一个方法,创建一个新的struct对象,并从函数返回它来模拟C中的一个基本“构造函数”方法。我意识到有几种可行的方法: 直接创建struct对象,无需卸载到方法 声明我的struct对象的所有成员变量,然后将其传递给“构造函数”方法 将要填充对象的值直接传递到“构造函数”方法中,并将结果存储在struct对象中 在一行中使用我的“构造函数”方法创建并使用struct对象,而不存储它 这是我的代码,你会明白我的意思: #incl
#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个字符的字符串,你的堆栈会被覆盖,程序可能会崩溃。啊。。。我真是太愚蠢了,我忘了我用显式边界实例化了我的数组。你的回答现在很有道理——给我一点时间把鸡蛋从我脸上拿开:)