鱼C论坛

 找回密码
 立即注册
查看: 58|回复: 3

[已解决]匿名结构体

[复制链接]
发表于 3 天前 From FishC Mobile | 显示全部楼层 |阅读模式
3鱼币
struct{int a;int c}a;
struct{int a;int c}c;
不能把a=c;
如果用强制转换行不行
最佳答案
3 天前
在 C 语言中,即使两个匿名结构体的成员完全相同,编译器也会将它们视为不同的类型。因此,直接赋值 `a = c;` 是不允许的,会产生编译错误。

使用强制转换可以绕过编译器的类型检查,但这样做是危险的:


  1. struct { int a; int c; } a;
  2. struct { int a; int c; } c;

  3. // 使用强制转换进行赋值(不推荐!)
  4. a = *(typeof(a)*)&c;
复制代码


或者使用更明确的强制转换:


  1. a = *((struct { int a; int c; } *)&c);
复制代码


但需要注意:
  • 这种操作违反了 C 语言的严格别名规则(strict aliasing)
  • 如果两个结构体的内存布局不完全相同(比如成员顺序或对齐方式不同),会导致未定义行为
  • 代码可读性和可维护性会变差


更好的解决方案:
  • 使用命名结构体类型(推荐)
  • 通过逐个成员赋值的方式复制数据
  • 使用 memcpy(但仍需确保内存布局完全相同)


示例(推荐做法):

  1. // 使用命名结构体
  2. struct MyStruct {
  3.     int a;
  4.     int c;
  5. };

  6. struct MyStruct a;
  7. struct MyStruct c;
  8. a = c;  // 现在可以合法赋值
复制代码


总之,虽然强制转换可以实现赋值,但由于潜在的风险,建议使用更安全的结构体定义方式。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

最佳答案

查看完整内容

在 C 语言中,即使两个匿名结构体的成员完全相同,编译器也会将它们视为不同的类型。因此,直接赋值 `a = c;` 是不允许的,会产生编译错误。 使用强制转换可以绕过编译器的类型检查,但这样做是危险的: 或者使用更明确的强制转换: 但需要注意: [*]这种操作违反了 C 语言的严格别名规则(strict aliasing) [*]如果两个结构体的内存布局不完全相同(比如成员顺序或对齐方式不同),会导致未定义行为 [*]代 ...
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 3 天前 | 显示全部楼层    本楼为最佳答案   
在 C 语言中,即使两个匿名结构体的成员完全相同,编译器也会将它们视为不同的类型。因此,直接赋值 `a = c;` 是不允许的,会产生编译错误。

使用强制转换可以绕过编译器的类型检查,但这样做是危险的:


  1. struct { int a; int c; } a;
  2. struct { int a; int c; } c;

  3. // 使用强制转换进行赋值(不推荐!)
  4. a = *(typeof(a)*)&c;
复制代码


或者使用更明确的强制转换:


  1. a = *((struct { int a; int c; } *)&c);
复制代码


但需要注意:
  • 这种操作违反了 C 语言的严格别名规则(strict aliasing)
  • 如果两个结构体的内存布局不完全相同(比如成员顺序或对齐方式不同),会导致未定义行为
  • 代码可读性和可维护性会变差


更好的解决方案:
  • 使用命名结构体类型(推荐)
  • 通过逐个成员赋值的方式复制数据
  • 使用 memcpy(但仍需确保内存布局完全相同)


示例(推荐做法):

  1. // 使用命名结构体
  2. struct MyStruct {
  3.     int a;
  4.     int c;
  5. };

  6. struct MyStruct a;
  7. struct MyStruct c;
  8. a = c;  // 现在可以合法赋值
复制代码


总之,虽然强制转换可以实现赋值,但由于潜在的风险,建议使用更安全的结构体定义方式。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 3 天前 From FishC Mobile | 显示全部楼层
FishC 发表于 2025-9-2 14:25
在 C 语言中,即使两个匿名结构体的成员完全相同,编译器也会将它们视为不同的类型。因此,直接赋值 `a = c ...

那如果是匿名结构体强制转换是不是也是可以
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 3 天前 | 显示全部楼层
bgc1314159 发表于 2025-09-02 14:46
FishC 发表于 2025-9-2 14:25
在 C 语言中,即使两个 ...


是的,你理解得没错。对于两个成员完全相同的匿名结构体,通过强制转换在技术上确实可以绕过编译器的类型检查,让赋值操作 `a = c;` 得以进行。

但是,必须极其谨慎地使用这种方法,因为它依赖于未定义行为(Undefined Behavior),程序的正确性无法得到保证。

具体做法如下:

struct { int a; int c; } a;
struct { int a; int c; } c;

// 假设 c 已经被赋值
c.a = 10;
c.c = 20;

// 使用强制转换进行赋值
a = *((struct {int a; int c;} *) &c);

// 现在 a 中的值应该和 c 一样了
printf("a.a = %d, a.c = %d\n", a.a, a.c); // 可能会输出 a.a = 10, a.c = 20


  1. #include <stdio.h>

  2. int main() {
  3.     struct { int a; int c; } a;
  4.     struct { int a; int c; } c;

  5.     c.a = 10;
  6.     c.c = 20;

  7.     // 关键的一步:强制转换
  8.     a = *((struct {int a; int c;} *) &c);

  9.     printf("a.a = %d, a.c = %d\n", a.a, a.c);
  10.     return 0;
  11. }
复制代码


为什么说这是危险且不推荐的?

  • 违反了严格别名规则(Strict Aliasing Rule):C/C++ 标准规定,通过一种类型的指针去访问另一种类型的对象是未定义行为。虽然很多编译器在实际中可能不会报错,但这并不能保证在所有平台和所有优化级别下都能正常工作。
  • 内存布局的假设:这个操作暗中假设了两个匿名结构体在内存中的布局(包括成员的顺序、对齐方式和填充字节)是完全一致的。虽然在这个简单的例子中看起来一样,但如果结构体复杂一些,或者在不同的编译环境下,这种假设就可能失效。
  • 可移植性和可维护性极差:这段代码非常晦涩,其他阅读代码的人很难理解其意图。而且,如果未来修改了其中一个结构体的成员,这段代码可能会悄无声息地崩溃,而不是给出一个清晰的编译错误。


真正推荐的解决方案:

  • 使用命名结构体:这是最清晰、最安全的方法。
  • 逐个成员手动赋值:如果必须使用匿名结构体,这是最安全的方式。
  • 使用 memcpy:如果你能 100% 确定两个结构体的内存布局完全相同,可以使用 memcpy(&a, &c, sizeof(a));。这同样有风险,但比指针强制转换稍微好理解一点。



  1. // 方法2:手动赋值(安全)
  2. a.a = c.a;
  3. a.c = c.c;

  4. // 方法3:使用 memcpy(需谨慎)
  5. #include <string.h>
  6. memcpy(&a, &c, sizeof(a));
复制代码


总结:强制转换可以让你“编译通过”,但它是一把没有护手的利刃,很容易伤到自己。在绝大多数情况下,都应该选择更安全、更明确的替代方案。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-9-5 17:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表