将结构指针转换为另一个结构

2024-04-23

此代码片段打印该值5。我不明白为什么。

#include <stdio.h>

struct A
{
    int x;
};

struct B
{
    struct A a;
    int y;
};

void printA(struct A *a)
{
    printf("A obj: %d\n", a->x);
}

int main(void)
{
    struct B b = {
        {
            5
        },
        10
    };
    
    struct A *a = (struct A*)&b;
    printA(a);
    
    printf("Done.\n");
    return 0;
}

当我创建时b,指向它的指针将指向数据{ {5}, 10 }.

当我施放时&b to struct A*,我向编译器保证这struct A*指向数据类型的单个数据元素的结构int。相反,我向它提供一个指向两个数据类型数据元素的结构的指针struct A, int.

即使第二个变量被忽略(因为struct A只有一个数据成员)我仍然为其提供一个结构,其成员为数据类型struct A, not int.

因此,当我通过a to printA, 线a->x执行,本质上是要求访问第一个数据元素a。第一个数据元素a是数据类型struct A,这是由于类型不匹配%d期待一个数字,而不是一个struct A.

这里究竟发生了什么?


语言律师对代码为何良好的解释:

  • C 中的任何指针都可以转换为任何其他指针类型。 (C17 6.3.2 §7)。
  • 转换后取消引用所指向的对象是否安全取决于:1) 类型是否兼容并因此正确对齐,以及 2) 所使用的相应指针类型是否允许别名。
  • 作为一种特殊情况,指向结构类型的指针相当于指向其第一个成员的指针。 C17 6.7.2 §15 的相关部分说:

    指向结构体对象的指针, 适当转换后,指向其初始成员(或者如果该成员是位字段,则指向中的单位 它所在的位置),反之亦然。

  • 这意味着(struct A*)&b很好。&b被适当地转换为正确的类型。

  • 不存在违反“严格别名”的情况,因为我们满足 C17 6.5 §7:

    对象的存储值只能由具有以下类型之一的左值表达式访问:

    • 与对象的有效类型兼容的类型, ...
    • 其成员中包含上述类型之一的聚合或联合类型

    初始成员的有效类型是struct A。打印函数内部发生的左值访问没问题。struct B也是一个聚合类型,包括struct A在其成员之间,因此无论顶部引用的初始成员规则如何,严格的别名违规都是不可能的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将结构指针转换为另一个结构 的相关文章

  • 在 JavaScript 中引用 C# 变量

    我已经阅读了很多线程 但我不明白为什么这不起作用 我正在创建一个将用作导航栏的 SharePoint Web 部件 一切都很顺利 直到我尝试在 JS 代码中引用 C 变量 这是来自 VisualWebPart1UserControl asc
  • 访问特征矩阵的行向量时复制或引用

    我正在使用的代码Eigen http eigen tuxfamily org index php title Main Page矩阵库 我注意到在整个代码中 有如下访问器 RowVector3f V size t vertex index
  • 为什么模板类的静态成员不唯一

    看一下下面的代码 include
  • 快速 log2(float x) 实现 C++

    我需要在 C 中非常快速地实现 log2 float x 函数 我发现了一个非常有趣的实现 而且速度非常快 include
  • 如何将动态数据写入 MVC 3 Razor 中的页面布局?

    我有带有 Razor 引擎的 MVC 3 C 项目 将动态数据写入 Layout cshtml 的方法和最佳实践是什么 例如 也许我想在网站的右上角显示用户名 该名称来自会话 数据库或基于用户登录的任何内容 更新 我也在寻找将某些数据渲染到
  • 如何在 Asp.Net Core 6 中向类型化 HttpClient 添加承载令牌身份验证

    我正在尝试使用 ASP Net Core 6 设置一个 Web api 以便用户可以到达我的端点 然后我使用特权帐户在幕后的 D365 中执行一些工作 我正在使用类型化的 HTTP 客户端 但我不确定如何插入承载身份验证 以便来自该客户端的
  • ptrace和waitpid有什么关系?

    我正在练习使用ptrace但我不太了解它和之间的关系waitpid 这是我的测试程序 int main int argc char argv pid t pid 22092 if ptrace PTRACE ATTACH pid NULL
  • 如何准备sql语句并绑定参数?

    不幸的是 文档 http www sqlite org完全缺乏示例 这真的很奇怪 就好像它假设所有读者都是优秀的程序员一样 然而 我对C 并且无法真正从文档中弄清楚如何真正准备和执行语句 我喜欢它的实施方式PDO for PHP 通常 我只
  • 如何将 mat 转换为 array2d

    我为dlib http dlib net face landmark detection ex cpp html那里的面部地标代码使用 array2d 来获取图像 但我喜欢使用 Mat 读取图像并转换为 array2d 因为 dlib 仅支
  • 如何使用 libclang 判断成员函数是 const 还是 volatile?

    我有一个实例CXCursor同类CXCursor CXXMethod 我想知道这个函数是否是const or volatile 例如 class Foo public void bar const void baz volatile voi
  • C++ 中可以使用匿名类作为返回类型吗?

    有没有办法在 C 中使用匿名类作为返回类型 我用谷歌搜索这可能有效 struct Test fun 但是这段代码无法编译 错误信息是 新类型不能在返回类型中定义 其实代码没有任何意义 我只是想弄清楚匿名类是否可以用作C 中的返回类型 这是我
  • 使用正则表达式解析日志文件

    我目前正在为我们的内部日志文件 由 log4php log4net 和 log4j 生成 开发一个解析器 到目前为止 我有一个很好的正则表达式来解析日志 除了一个烦人的一点 一些日志消息跨越多行 我无法正确匹配 我现在的正则表达式是这样的
  • 如何修复此 YCrCb -> RBG 转换公式?

    我使用的公式来自这个问题 https stackoverflow com questions 8838481 kcvpixelformattype 420ypcbcr8biplanarfullrange frame to uiimage c
  • WPF ComboBox 中具有本地化名称的枚举

    我有一个列出枚举的组合框 enum StatusEnum Open 1 Closed 2 InProgress 3
  • Bazel:将编译标志添加到默认 C++ 工具链

    我想向默认的 C 工具链添加一些编译器和链接器标志 以便我构建的所有目标 本地或导入 共享它们 我知道可以定义我自己的工具链 但我不想这样做 因为它非常复杂且容易出错 理想情况下我想要这样的东西 cc toolchain cc defaul
  • 这个元组创建习惯有名字吗?

    On the 增加邮件列表 http lists boost org Archives boost 2014 06 214213 php LouisDionne 最近发布了以下创建类似元组的实体的巧妙技巧 include
  • 从 cin 读取整数序列并将它们存储在向量中

    这就是我读取整数的方法std cin并将它们存储在向量中 int number vector
  • 为什么将未使用的返回值转换为 void?

    int fn void whatever void fn 是否有任何理由将未使用的返回值强制转换为 void 或者我认为这完全是浪费时间 David s answer https stackoverflow com questions 68
  • 为什么在 C++ 类中的数据成员上使用像 m_ 这样的前缀?

    许多 C 代码使用语法约定来标记数据成员 常见的例子包括 m memberName对于公共成员 在所有使用公共成员的情况下 memberName对于私人会员或所有会员 其他人尝试强制使用this gt member每当使用数据成员时 根据我
  • 从最大到最小的3个整数

    我是 C 初学者 我使用 编程 使用 C 的原理与实践 第二版 问题如下 编写一个程序 提示用户输入三个整数值 然后以逗号分隔的数字顺序输出这些值 如果两个值相同 则应将它们排列在一起 include

随机推荐