在C语言中,结构体赋值可通过直接赋值(=操作符)、逐个成员赋值、指定初始化(如.name="value",C99标准推荐)或memcpy()实现,但需注意字符数组必须用strcpy()赋值(不可直接用=),且结构体包含指针成员时直接赋值会导致浅拷贝问题(两个结构体指向同一内存地址)。

在C语言中,结构体(struct)是一种重要的复合数据类型,可以将不同类型的数据组合成一个整体。结构体赋值是C语言编程中的常见操作,以下是几种主要的赋值方法。

1. 直接赋值(使用=操作符)

这是最简单、最常用的方法,适用于两个同类型的结构体变量之间。

struct Person {
    char name[50];
    int age;
    float score;
};

int main() {
    struct Person p1, p2;
    
    // 先给p1赋值
    strcpy(p1.name, "Alice");
    p1.age = 25;
    p1.score = 90.5;
    
    // 直接赋值
    p2 = p1;  // 将p1的整个内容复制给p2
    
    printf("Name: %s, Age: %d, Score: %.1f\n", p2.name, p2.age, p2.score);
    return 0;
}

注意:如果结构体包含指针成员,这种赋值会导致"浅拷贝"问题(两个结构体指向同一个内存地址)。

2. 逐个成员赋值

通过点运算符(.)或箭头运算符(->)逐个给结构体成员赋值。

struct Person p;
strcpy(p.name, "Bob");  // 字符数组不能直接用=赋值
p.age = 30;
p.score = 85.5;

重要提示:对于结构体中的字符数组(字符串),不能直接使用=赋值(如p.name = "Bob";是错误的),必须使用strcpy()函数。

3. 初始化列表赋值

在定义结构体变量时,使用初始化列表一次性赋值。

struct Person p = {"Alice", 25, 90.5};

指定初始化(C99标准引入,推荐使用):

struct Person p = {.name = "Alice", .age = 25, .score = 90.5};

这种初始化方式的好处是成员初始化顺序和个数可变,扩展性好,增加字段时不需要修改大量代码。

4. memcpy()函数赋值

使用标准库函数memcpy()进行内存复制。

#include <string.h>
#include <stdio.h>

struct Person {
    char name[50];
    int age;
    float score;
};

int main() {
    struct Person p1, p2;
    
    strcpy(p1.name, "Alice");
    p1.age = 25;
    p1.score = 90.5;
    
    // 使用memcpy进行赋值
    memcpy(&p2, &p1, sizeof(struct Person));
    
    printf("Name: %s, Age: %d, Score: %.1f\n", p2.name, p2.age, p2.score);
    return 0;
}

5. 结构体指针赋值

将一个结构体指针赋给另一个结构体指针,使它们指向同一个结构体。

struct Person *p1 = &person1;
struct Person *p2 = p1;  // p2和p1指向同一个结构体

重要注意事项

  1. 字符数组赋值:结构体中的字符数组(字符串)不能直接用=赋值,必须使用strcpy()函数。

  2. 初始化 vs 赋值

    • 初始化是在变量定义时完成的,是变量定义的一部分
    • 赋值是在变量定义完成之后进行的
  3. 浅拷贝问题:如果结构体包含指针成员,使用=直接赋值会导致浅拷贝(两个结构体指向同一个内存地址),修改一个会影响另一个。

  4. 结构体赋值的限制:不能在赋值语句中使用大括号初始化,例如:

    struct Person p;
    p = {1, 2, 3};  // 错误!不能这样赋值
    

推荐做法

  • 对于简单的结构体,使用指定初始化(如.name = "Alice")方式,提高代码可读性和可维护性
  • 如果结构体包含指针成员,需要考虑深拷贝(为指针指向的内存分配新空间并复制内容)
  • 对于需要频繁赋值的结构体,可以考虑编写专门的赋值函数