当我在主函数之外初始化结构成员时,为啥这个 c 程序会出错?

Posted

技术标签:

【中文标题】当我在主函数之外初始化结构成员时,为啥这个 c 程序会出错?【英文标题】:Why this c-program gives error when I initialize structure member outside the main function?当我在主函数之外初始化结构成员时,为什么这个 c 程序会出错? 【发布时间】:2021-06-04 18:51:01 【问题描述】:

为什么当我在 main 函数之外初始化结构成员(user.usernameuser.pin)时,这个 c 程序会出错?但是当我在 main 函数内初始化它时,一切都变得正常了。

还有什么方法可以初始化一个char数组(结构的成员)?

#include <stdio.h>

typedef struct 
    int pin;
    char username[20];
 portal;

portal user;

// user.username = "alex"; 
// user.pin[20] = 1234;  //Why this gives error when I intialize it here(i.e outside the main function)?

int main() 
    user.username = "alex"; //How to intialize a memeber(having type char) of structure?
    user.pin[20] = 1234;

    printf("WELCOME TO PORTAL\n");
    printf("ENTER YOUR USERNAME:\n");
    scanf("%[^\n]%*c", user.username);
    .
    .
    .

实际上,当我在 main 函数之外初始化 user.username 时,我得到了这个输出。

【问题讨论】:

你所做的是赋值,它必须在函数内部,就像任何代码一样。您需要的是结构初始化,查找它的语法 没有user.pin[20]pin 不是数组。 【参考方案1】:

// user.username = "alex"; // user.pin[20] = 1234; //为什么这给出 在这里初始化时出错(即在主函数之外)?

这不是初始化。这是赋值语句。外部函数只能放置声明而不是语句。

此外,即使作为陈述,它们也是不正确的。

看看你的结构定义

typedef struct

 int pin;
 char username[20];
portal;

数据成员pin 的类型为int。它不是一个数组。所以这个作业

user.pin[20] = 1234;

没有意义。你至少应该这样写

user.pin = 1234;

另一方面,数据成员username 是一个字符数组。数组没有赋值运算符。您必须将字符串复制到字符数组中。例如

#include <string.h>

//...

strcpy( user.username, "alex" );

但是您可以在声明对象user 时对其进行初始化。例如

portal user =  1234, "alex" ;

portal user =  .pin = 1234, .username = "alex" ;

这是一个演示程序

#include <stdio.h>

typedef struct

    int pin;
    char username[20];
 portal;

portal user =  .pin = 1234, .username = "alex" ;

int main(void) 

    printf( "pin = %d, user name = %s\n", user.pin, user.username );

    return 0;

程序输出是

pin = 1234, user name = alex

【讨论】:

【参考方案2】:

在 C 语言中,除了函数之外,您只能有声明和预处理器指令。源文本user.username = "alex"; 是一个语句,user.pin[20] = 1234; 也是。出现编译器错误消息是因为编译器需要声明,而您的语句不符合预期。

要在定义对象时对其进行初始化,请使用带有定义的语法进行初始化,而不是编写单独的语句。 user 可以使用以下任一方式定义和初始化:

portal user =  "alex", 1234 ;
portal user =  .username = "alex", .pin = 1234 ;

虽然定义在初始化时使用=,但这不是一个赋值。这是= 符号的不同用法,具有类似的效果(将此值放在那个位置)。另一个区别是,在初始化中,您可以使用字符串文字来初始化字符数组。在声明中,你不能。

user 赋予初始值的另一种方法是在main 中编写语句:

int main(void)

    strcpy(user.username, "alex");
    user.pin = 1234;
    …

【讨论】:

【参考方案3】:

全局变量可以作为定义点初始化,但不能作为独立语句:

portal user =  1234, "alex" ;  // definition with an initializer

user.pin = 1234;        // assignment is invalid outside a function
user.username = "Alex"; // assignment is invalid outside a function and assigning to an array is invalid as well

结构体成员可以在函数内部设置,但数组内容不能用=操作符赋值,需要显式赋值数组元素或使用函数调用:

int main() 
    char extra[20];

    user.pin = 1234;         // OK

    user.username[0] = 'A';  // tedious, but OK
    user.username[0] = 'l';
    user.username[0] = 'e';
    user.username[0] = 'x';
    user.username[0] = '\0'; 

    strcpy(user.username, "Alex"); // OK if username has at least 5 elements

    snprintf(user.username, sizeof user.username, "%s", "Alex"); // overkill, but OK

    // read values from stdin:
    // scanf will return the number of members successfully converted:
    switch (scanf("%d%19s%19[^\n]", &user.pin, user.username, extra)) 
      case EOF:
        printf("premature end of file\n");
        break;
      case 0:
        printf("input is not a number for user.pin\n");
        break;
      case 1:
        printf("user.pin=%d, no input for user.username\n", user.pin);
        break;
      case 2:
        printf("user.pin=%d, user.username=%s\n", user.pin, user.username);
        break;
      case 3:
        printf("user.pin=%d, user.username=%s, extra input=%s\n", user.pin, user.username, extra);
        break;
    
    return 0;

【讨论】:

【参考方案4】:

该结构成员已经初始化。当您在 main 之外执行此操作时,编译器可以通过立即将其设置为字符串文字来优化它。

如果输入了main,那么初始化为时已晚。编译器不假设main 保证被调用或立即调用。因此main 中的语句不是初始化而是赋值。您不能分配给字符数组,这就是 strcpy 和相关函数的用途。

这应该可行:

strcpy(user.username, "Alex")

snprintf(user.username, sizeof user.username, "Alex");

【讨论】:

以上是关于当我在主函数之外初始化结构成员时,为啥这个 c 程序会出错?的主要内容,如果未能解决你的问题,请参考以下文章

c语言如何对结构体某一成员初始化

结构体指针

为啥就地成员初始化在 C++11 中使用复制构造函数?

即使只有主函数,在主函数外部声明变量也会改变输出

成员函数线程安全吗?

如何从外部函数 C++ 访问动态结构?