C- 一个程序引发的问题

C程序如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct student_t
{char *id;char *name;char *score;
};typedef struct student_t *Student_t;void print_stu_info(Student_t stu)
{printf("%s  %s  %s\n", stu->id, stu->name, stu->score);
}int main()
{Student_t stu = malloc(sizeof(*stu));stu->id = "001";stu->name = "xiaonan";stu->score = "95";print_stu_info(stu);*((char **)((char *)stu + 2*sizeof(char *))) = "100";print_stu_info(stu);return 0;
}

程序运行结果如下:

majn@tiger:~/C_Project/dl_project$ ./hack_struct 
001  xiaonan  95
001  xiaonan  100

问题一


Student_t stu = malloc(sizeof(*stu));

第一次见这种写法,真的没有问题吗?写成

Student_t stu = malloc(sizeof(*Student_t)); 

为什么编译报错?


在这行代码中出现了错误:

Student_t stu = malloc(sizeof(*Student_t));

问题在于 *Student_t。在这里,Student_t 是一个类型,而不是一个变量。不能对类型进行解引用。

正确的方式是,使用 sizeof(struct student_t)sizeof(*stu) 来获取结构体的大小。如果我们要分配一个结构体的大小并返回一个指向该结构体的指针,应该这样写:

Student_t stu = malloc(sizeof(struct student_t));

或者:

Student_t stu = malloc(sizeof(*stu));

将上述更正后的代码行替换原有代码,应该能够成功编译。


关于第一种写法的问题,这实际上与C语言的声明和初始化语法有关。

在C语言中,当我们写:

Student_t stu = malloc(sizeof(*stu));

以下是发生的事情的简化描述:

  1. 编译器首先处理 Student_t stu 部分。这里,它知道声明了一个名为 stuStudent_t 类型的指针变量。从这一点开始,stu 已经被声明并可以在其后的代码中使用。

  2. 接下来,编译器处理 = malloc(sizeof(*stu)) 部分。这时,由于 stu 已经被声明,所以可以在 sizeof(*stu) 中使用它。

因此,尽管 = 是右结合的,但在整个声明和初始化过程中,声明总是先于初始化发生。

如果将这两个步骤分开,那么确实需要确保在使用一个变量之前已经声明了它。但在同一语句中进行声明和初始化时,该语句的声明部分会首先被处理。


问题二

如何通过直接操作内存地址的方式来修改 stu->score 的值?

如果想通过直接操作内存地址来修改 stu->score 的值,首先,需要确保准确地计算了偏移量,并且将正确的值赋给正确的地址。

struct student_t 中,字段按以下顺序出现:

  1. char *id
  2. char *name
  3. char *score

所以,stu 指针首先指向 id,然后是 name,最后是 score

我们可以通过增加 stu 的地址来修改 score,但需要知道系统的指针大小(通常是 4 字节(32位系统)或 8 字节(64位系统))。

以下是可能的写法(假设在 64 位系统上):

*((char **)((char *)stu + 2*sizeof(char *))) = "100";

解释:

  • 首先,我们将 stu 转换为 char * 类型,使我们能够按字节递增其地址。
  • 接下来,我们增加了 2 * sizeof(char *) 字节,这样我们就可以跳过前两个 char * 字段,指向 score
  • 然后我们将结果转换回 char ** 类型,以便我们可以将字符串的地址("100")赋给它。

下面,我们来详细地探讨这行代码的每一个部分:

首先,来看这个代码的目的:它旨在直接更改 stu->score 的指针值,使其指向新的字符串字面量 "100"

现在,我们一步一步来分析这行代码:

  1. (char *)stu:
    这将 stu 指针从 Student_t 类型转换为一个字符指针 (char *)。这样做允许我们以字节为单位进行指针算术。

  2. 2*sizeof(char *):
    这里我们计算两个指针的大小。每个 char * 指针的大小通常为 4 字节(32位系统)或 8 字节(64位系统)。因此,这部分代码计算 stu 结构中前两个 char * 指针(idname)所占用的总字节。

  3. (char *)stu + 2*sizeof(char *):
    这将上述两个部分结合起来,即将 stu 的起始地址增加了前两个 char * 指针所占用的字节,从而将地址定位到 score 字段。

  4. (char **)((char *)stu + 2*sizeof(char *)):
    现在,我们再次进行类型转换,将计算出的 score 地址从 char * 转换为 char **。因为我们最终的目标是更改一个指针的值(指向一个新的字符串),而不仅仅是更改一个字符。

  5. ((char **)((char *)stu + 2*sizeof(char *))) = “100”:
    最后,我们使用解引用运算符 * 来访问和更改 score 指针的值,使其指向新的字符串 "100"

直接操作内存地址是非常危险的,并且容易引入错误。这种做法破坏了抽象,使代码变得难以阅读和维护。因此,在实际编程中,应尽量避免使用这样的方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/90621.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【图像处理】SIFT角点特征提取原理

一、说明 提起在OpenCV中的特征点提取&#xff0c;可以列出Harris&#xff0c;可以使用SIFT算法或SURF算法来检测图像中的角特征点。本篇围绕sift的特征点提取&#xff0c;只是管中窥豹&#xff0c;而更多的特征点算法有&#xff1a; Harris & Stephens / Shi–Tomasi 角点…

【面试题】2023前端面试真题之JS篇

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 表妹一键制作自己的五星红旗国庆头像&#xff0c;超好看 世界上只有一种真正的英雄主义&#xff0c;那就是看清生活的真相之后&#xff0c;依然热爱生活。…

成为威胁:网络安全中的动手威胁模拟案例

不断变化的网络威胁形势要求组织为其网络安全团队配备必要的技能来检测、响应和防御恶意攻击。然而&#xff0c;在研究中发现并继续探索的最令人惊讶的事情是&#xff0c;欺骗当前的网络安全防御是多么容易。 防病毒程序建立在庞大的签名数据库之上&#xff0c;只需更改程序内…

《The Rise and Potential of Large Language Model Based Agents: A Survey》全文翻译

The Rise and Potential of Large Language Model Based Agents: A Surve - 基于 LLMs 的代理的兴起和潜力&#xff1a;一项调查 论文信息摘要1. 介绍2. 背景2.1 AI 代理的起源2.2 代理研究的技术趋势2.3 为什么大语言模型适合作为代理大脑的主要组件 3. 代理的诞生&#xff1a…

数据库系统课设——基于python+pyqt5+mysql的酒店管理系统(可直接运行)--GUI编程(2)

几个月之前写的一个项目&#xff0c;通过这个项目&#xff0c;你能学到关于数据库的触发器知识&#xff0c;python的基本语法&#xff0c;python一些第三方库的使用&#xff0c;包括python如何将前后端连接起来&#xff08;界面和数据&#xff09;&#xff0c;还有界面的设计等…

神经辐射场(NeRF)2023最新论文及源代码合集

神经辐射场&#xff08;NeRF&#xff09;作为一种先进的计算机图形学技术&#xff0c;能够生成高质量的三维重建模型&#xff0c;在计算机图形学、计算机视觉、增强现实等领域都有着广泛的应用前景&#xff0c;因此&#xff0c;自2020年惊艳亮相后&#xff0c;神经辐射场也成为…

python安装第三方模块方法

正常情况下安装python第三方模块没啥说的&#xff0c;但是由于python安装模块默认是在外网下载安装&#xff0c;牵扯外网网速问题&#xff0c;所以可以配置下使用国内某镜像源来下载模块 python -m pip install xxxxxxxxxxx 和 pip install xxxxxxxxxx 的命令都可下载安装第三…

raw智能照片处理工具DxO PureRAW mac介绍

DxO PureRAW Mac版是一款raw智能照片处理工具&#xff0c;该软件采用了智能技术&#xff0c;以解决影响所有RAW文件的七个问题&#xff1a;去马赛克&#xff0c;降噪&#xff0c;波纹&#xff0c;变形&#xff0c;色差&#xff0c;不想要的渐晕&#xff0c;以及缺乏清晰度。 Dx…

李宏毅机器学习第一课(结尾附作业模型详细分析)

机器学习就是让机器找一个函数f&#xff0c;这个函数f是通过计算机找出来的 如果参数少的话&#xff0c;我们可以使用暴搜&#xff0c;但是如果参数特别多的话&#xff0c;我们就要使用Gradient Descent Regression (输出的是一个scalar数值) Classification &#xff08;在…

【C++】C++入门

一、C 关键字&#xff08;C98&#xff09; C 总计 63 个关键字&#xff0c;C 语言 32 个关键字。C 语言的关键字在 C 中继续可以使用。 C 兼容 C 的绝大多数语法。 二、命名空间 在 C / C 中&#xff0c;变量、函数和类都是大量存在的&#xff0c;这些变量、函数和类的名称将都…

iOS UWB——NI框架部分类

前文介绍iOS中NI框架的实现流程以及简单的应用示例&#xff0c;本文中针对NI框架中的部分类以及相关会话生命周期管理函数进行了简单的介绍。 NI框架关键类 Class NISession class NISession : NSObject概述 NISession类是整个Nearby Interaction类的核心&#xff0c;所有会…

DVWA-impossible代码审计

本篇文章针对于DVWA靶场的impossible级别进行代码审计&#xff0c;基于DVWA的每一个漏洞的impossible级别&#xff0c;从整体思路上出发&#xff0c;进行代码审计&#xff0c;最后对其总结。从中可以学习到一些漏洞的防御手法&#xff0c;并且对漏洞有更深入的理解。 文章目录 …

led台灯哪个牌子最好?2022最新的台灯牌子排名

想要选好护眼台灯首先我们要知道什么是护眼台灯&#xff0c;大的方向来看&#xff0c;护眼台灯就是可以保护视力的台灯&#xff0c;深入些讲就是具备让灯发出接近自然光特性的光线&#xff0c;同时光线不会伤害人眼而出现造成眼部不适甚至是视力降低的照明设备。 从细节上看就…

Linux——补充点(页表映射及LWP)

目录 补充点1&#xff1a;进程地址空间堆区管理 补充点2&#xff1a;Linux内核进程上下文切换 补充点3&#xff1a;页表映射 补充点4&#xff1a;两级页表 补充点1&#xff1a;进程地址空间堆区管理 Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程&#…

使用perming加速训练可预测的模型

监督学习模型的训练流程 perming是一个主要在支持CUDA加速的Windows操作系统上架构的机器学习算法&#xff0c;基于感知机模型来解决分布在欧式空间中线性不可分数据集的解决方案&#xff0c;是基于PyTorch中预定义的可调用函数&#xff0c;设计的一个面向大规模结构化数据集的…

【Java 进阶篇】MySQL多表查询之外连接详解

在MySQL数据库中&#xff0c;多表查询是一种常见且强大的功能&#xff0c;允许您在多个表之间执行联接操作&#xff0c;从而检索、过滤和组合数据。在本篇博客中&#xff0c;我们将深入探讨多表查询的一种类型&#xff0c;即外连接&#xff08;Outer Join&#xff09;&#xff…

医疗小程序开发:技术门槛高?

随着移动互联网的普及&#xff0c;医疗行业也逐渐转向线上。医疗小程序开发成为了很多企业和医疗机构关注的焦点。但是&#xff0c;对于一些技术小白来说&#xff0c;可能会觉得医疗小程序开发技术门槛高&#xff0c;无从下手。实际上&#xff0c;使用乔拓云平台进入后台&#…

C理解(一):内存与位操作

本文主要探讨C语言的内存和为操作操作相关知识。 冯诺依曼结构和哈佛结构 冯诺依曼结构&#xff1a;数据和代码放在一起,便于读取和修改,安全性低 哈佛结构是&#xff1a;数据和代码分开存放,安全性高,读取和修麻烦 内存 内存是用来存储全局变量、局…

求第n项的因子数量

最近笔试期间遇到一个难题&#xff0c;现在终于解决了&#xff0c;感谢各路大佬的指点&#xff0c;我在这里分享一下结果。 小红拿到一个数列满足&#xff1a; f(1) a&#xff1b; f(2) b&#xff1b; f(i) f(i-1) * f(i-2) * c^d 题目要求计算出第n项的因子数…

DPDK系列之三十一DPDK的并行机制简介

一、并行机制 什么是并行机制&#xff1f;这个很多开发者的眼中&#xff0c;其实是模糊的。可能说起来头头是道&#xff0c;但是细一查究竟&#xff0c;发现都是飘在空中的东西。在前面的“多核和多CPU编程”中&#xff0c;对并行机制已经进行了较深入的分析&#xff0c;这里只…