我尝试创建一个函数来接收const char *
变量来初始化结构的char *
成员并返回所述结构。问题是我得到一个警告,说我正在转换整数指针。此外,当我尝试打印时,它并不像我预期的那样工作,尽管在函数外部初始化可以完美地工作。我使用没有标志的gcc
来编译它。我制作了我的代码的最小版本,它给了我同样的警告:
#include <stdio.h>
struct Person {
char name[128];
};
struct Person initialize_person(const char *name);
main() {
/* raises warning: */
struct Person person1;
person1 = initialize_person("John Doe");
/* does not raise a warning: */
struct Person person2 = {"Mary Foo"};
printf("person1: %s\n" /* prints garbage */
"person2: %s\n", /* prints what is expected */
person1.name, person2.name);
return 0;
}
struct Person initialize_person(const char *name)
{
struct Person new_person = {name};
/* I thought name would be equivalent to
litterally "John Doe" here */
return new_person;
}
它提出了这个警告:
main.c: In function ‘initialize_person’:
main.c:25:9: warning: initialization makes integer from pointer without a cast [enabled by default]
struct Person new_person = {name};
^
main.c:25:9: warning: (near initialization for ‘new_person.name[0]’) [enabled by default]
答案 0 :(得分:3)
这实际上与结构无关,而是与char数组有关。
char[]
的初始值设定项不能是指向char的指针。它必须是字符串文字或可转换为char
的值序列。
(寻求实际正式定义的帮助,如果有人的话。)
换句话说:
char foo[128] = "foo";
或
char foo[128] = {1, 2, 3};
问题是编译器需要一个常量表达式,因此它可以生成用这些值初始化结构的代码。关键是初始化程序的长度是已知的。使用您的代码尝试使用指针时,长度是未知的。
在我提出解决方案之前的一些建议:不要将值按结构传递给函数,也不要将它们从函数中返回。使用指向结构的指针要高效得多,因为结构不需要复制。
bool initialize_person(struct Person *person; const char *name)
{
if (strlen(name) > sizeof(person->name - 1) {
// Name is too long
return false;
}
strcpy(person->name, name);
return true;
}
int main(void)
{
struct Person person1;
if (!initialize_person(&person1, "John Doe")) {
exit(1);
}
return 0;
}
答案 1 :(得分:3)
鉴于此声明:
struct Person { char name[128]; };
您不能像这样初始化struct Person
:
struct Person initialize_person(const char *name) { struct Person new_person = {name};
字符串文字与char *
(尽管有const
nence)不同,与数组不是指针的方式非常相似。要从变量数据初始化struct
成员char
数组,您需要显式复制。这与您可能达到的目标一样接近:
struct Person new_person;
strncpy(new_person.name, name, sizeof(new_person.name) - 1);
但请注意,当您返回struct
时,您将创建另一个副本。相反,请考虑将指针传递给要初始化的struct
以及初始化数据,或者动态分配struct
,初始化它,并返回指向结果的指针。
答案 2 :(得分:2)
问题在于new_person的初始化程序。
struct Person new_person = {name};
它不会将name指向的数组复制到数组new_person.name
相反,它做到了这一点:
struct Person new_person; new_person.name[0] = name;
所以它试图将指针复制到char,因此警告。 new_person.name[0]
获取的值与您想要的值不同,并且数组的其余部分保持未初始化状态,因此会打印垃圾。
解决问题的方法不正确:
struct Person new_person =
{name[0],name[1],name[2],name[3],name[4],name[5],name[6],name[7],name[8]};
你的程序会像那样正常工作。但只是因为&#34; John Doe&#34;和#34; Mary Foo&#34;最多8个字符。它会因较大的字符串而失败 解决问题的正确方法是:
struct Person new_person;
sprintf(new_person.name, "%.127s", name);
即使使用不符合名称的空间的字符串,这也能正常工作。它们将被剪切,只使用127个第一个字符。