结构和其他数据形式

0x01 结构声明

结构声明(structure declaration)描述了一个结构的组织布局。

struct book{char title[MAXTITL];char author[MAXAUTL];float value;
};

该声明描述了一个由两个字符数组和一个float类型变量组成的结构。该声明并未创建实际的数据对象,只描述了该对象由什么组成。
struct,它表明跟在其后的是一个结构,后面是一个可选的标记(该例中是 book),稍后程序中可以使用该标记引用该结构。
我们在后面的程序中可以这样声明:

struct book library;

这把library声明为一个使用book结构布局的结构变量。

#include "stdio.h"#define MAXTITL 30
#define MAXAUTL 30struct book{char title[MAXTITL];char author[MAXAUTL];float value;
};int a;
struct book book2;
int main()
{struct book book1={"Hello","d1l1endh",7.6};printf("title=%s\n",book1.title);printf("author=%s\n",book1.author);printf("value=%f\n",book1.value);return 0;
}

反汇编我们看看结构声明会产生什么:
在这里插入图片描述
struct book相当于一个类型,和int 相似,book2相当于a,结构布局告诉编译器如何表示数据,但是它并未让编译器为数据分配空间。

0x02 定义结构变量

struct book book2;

编译器执行这行代码便创建了一个结构变量book2。编译器使用book模
板为该变量分配空间:一个内含MAXTITL个元素的char数组、一个内含
MAXAUTL个元素的char数组和一个float类型的变量。这些存储空间都与一
个名称book2结合在一起
struct book book2;
是以下声明的简化:

struct book {
char title[MAXTITL];
char author[AXAUTL];
float value;
} book2; 

换言之,声明结构的过程和定义结构变量的过程可以组合成一个步骤。如果打算多次使用结构模板,就要使用带标记的形式;或者,使用typedef。

2.1 初始化结构

初始化一个结构变量(ANSI之前,不能用自动变量初始化结构;ANSI之后可以用任意存储类别)与初始化数组的语法类似:

struct book book1={"Hello","d1l1endh",7.6};
2.2 访问结构成员

使用结构成员运算符——点(.)访问结构中的成员。

0x03 嵌套结构

在一个结构中包含另一个结构

#include "stdio.h"#define LEN 30struct names{char first[LEN];char last[LEN];
};struct guy{struct names handle;char favfood[LEN];char job[LEN];float income;};int main()
{struct guy fellow={{"Ell","end"},"salmon","programmer",100000};printf("firset=%s\n",fellow.handle.first);printf("job=%s\n",fellow.job);printf("income=%f\n",fellow.income);return 0;
}

在这里插入图片描述

访问嵌套结构的成员,这需要使用两次点运算符。handle是fellow的成员,first是handle的成员

0x04 指向结构的指针

4.1 声明和初始化指针

我们定义一个int类型指针是:

int *p;

结构也是一种类型,所以声明结构体指针很简单

struct guy *him;

struct guy 是一种类型,相当于int,这个语法和其他指针声明一样。该声明并未创建一个新的结构,但是指针him现在可以指向任意现有的guy类型的结构。如果barney是一个guy类型的结构,可以这样写:

him = &barney;

和数组不同的是,结构名并不是结构的地址,因此要在结构名前面加上&运算符。

4.2 用指针访问成员

使用->运算符。
->运算符后面的结构指针和.运算符后面的结构名工作方式相同
如果him == &barney,那么him->income 即是 barney.income

4.3 向函数传递结构的信息

这里我们重点说传递结构的地址和传递结构
传递结构的地址

#include "stdio.h"#define LEN 30struct names{char first[LEN];char last[LEN];
};struct guy{struct names handle;char favfood[LEN];char job[LEN];float income;};double sum(struct guy *);int main()
{struct guy fellow={{"Ell","end"},"salmon","programmer",100000};double sum_income=sum(&fellow);//printf("firset=%s\n",fellow.handle.first);//printf("job=%s\n",fellow.job);printf("sum_income=%f\n",sum_income);return 0;
}double sum(struct guy *people)
{return (people->income+people->income);
}

在这里插入图片描述
因为结构名不是其地址别名,所以我们必须用&运算符,然后通过->运算符获取值

传递结构

#include "stdio.h"#define LEN 30struct names{char first[LEN];char last[LEN];
};struct guy{struct names handle;char favfood[LEN];char job[LEN];float income;};double sum(struct guy );int main()
{struct guy fellow={{"Ell","end"},"salmon","programmer",100000};double sum_income=sum(fellow);//printf("firset=%s\n",fellow.handle.first);//printf("job=%s\n",fellow.job);printf("sum_income=%f\n",sum_income);return 0;
}double sum(struct guy people)
{return (people.income+people.income);
}

传递结构直接把结构名当参数就行

0x05 typedef

typedef工具是一个高级数据特性,利用typedef可以为某一类型自定义名称。

typedef unsigned char BYTE;

随后,便可使用BYTE来定义变量:

BYTE x, y[10], * z;

该定义的作用域取决于typedef定义所在的位置。

0x06 函数与指针

声明一个函数指针时,必须声明指针指向的函数类型。为了指明函数类型,要指明函数签名,即函数的返回类型和形参类型。

void ToUpper(char *); // 把字符串中的字符转换成大写字符

ToUpper()函数的类型是“带char * 类型参数、返回类型是void的数”。

void (*pf)(char *);  // pf 是一个指向函数的指针

第1对圆括号把*和pf括起来,表明pf是一个指向函数的指针
把**函数名ToUpper替换为表达式(*pf)**是创建指向函数指针最简单的方式。
所以,如果想声明一个指向某类型函数的指针,可以写出该函数的原型后把函数名替换成(*pf)形式的表达式,创建函数指针声明。

#include "stdio.h"void add(int a,int b);void main(void)
{int a=4,b=3,s=0;void (*funp)(int a,int b);funp=add;(*funp)(a,b);funp(a,b);}void add(int a,int b)
{printf("a+b=%d\n",a+b);}

在这里插入图片描述
声明一个函数指针时,必须声明指针指向的函数类型。包括返回值、参数,如果想声明一个指向某类型函数的指针,可以写出该函数的原型后把函数名替换成(*pf)形式的表达式,这样就声明好一个函数指针了。用函数指针调用函数是有两种方式:

  • 指针名(参数)
  • (* 指针名)(参数)
    我们反汇编看一下
9:        void (*funp)(int a,int b);
10:       funp=add;
00410B2D C7 45 F0 0F 10 40 00 mov         dword ptr [ebp-10h],offset @ILT+10(_add) (0040100f)
11:       (*funp)(a,b);
00410B34 8B F4                mov         esi,esp
00410B36 8B 45 F8             mov         eax,dword ptr [ebp-8]
00410B39 50                   push        eax
00410B3A 8B 4D FC             mov         ecx,dword ptr [ebp-4]
00410B3D 51                   push        ecx
00410B3E FF 55 F0             call        dword ptr [ebp-10h]
00410B41 83 C4 08             add         esp,8
00410B44 3B F4                cmp         esi,esp
00410B46 E8 E5 06 FF FF       call        __chkesp (00401230)

可以看出,把首地址赋值给我们的函数指针,也就是把函数首地址放到dword ptr [ebp-10h]里,调用的时候直接call dword ptr [ebp-10h],和平常调用函数一样

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

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

相关文章

添加LinkServer的两句代码

sp_addlinkedserver linkserver,,SQLOLEDB,linkserver.comsp_addlinkedsrvlogin linkserver,false,null,sa,asdf第一句是添加一个名字为linkserver的链接服务器 地址是linkserver.com第二句是针对第一句添加的Linkserver添加一个访问帐号两句不能同时执行 要第一句执行成功后执…

Cobaltstrike4.0系列教程(一)----简介与安装

0x01-Cobaltstrike简介 Cobalt Strike是一款美国Red Team开发的渗透测试神器,常被业界人称为CS。这款神器许多大佬们都已经玩的很6,我一个菜鸡玩的略有心得,因此写一下自己的Cobaltstrike系列文章,希望给各位一点帮助。 最近这个…

qt 试用 (3)配置编译源代码及调试

qt 试用 (3)配置编译源代码及调试qt creater是一个集成ide,像vc一样容易使用,所以首先下载带qt creater的qt sdk Offline installer - 1.4 GB http://qt.nokia.com/downloads/sdk-windows-cpp-offline这里的lib没有pdb和源代码…

cobaltstrick4.0系列教程(2)---用户接口

0x01 概述 Cobalt Strike 用户接口分为两部分。接口的顶部是会话或目标的视觉化展示。接口的底部展示了每个你与之交互的 Cobalt Strike 功能或会话的标签页。你可以点击这两部分之间的区域、按你的喜好重新调整这两个区域的大小。 0x02 工具条 Cobalt Strike 顶部的工具条…

cobalt strick 4.0系列教程(3)---数据管理

0x01 概述 Cobalt Strike 的团队服务器是行动期间 Cobalt Strike 收集的所有信息的中间商。Cobalt Strike 解析来自它的 Beacon payload 的输出,提取出目标、服务和凭据。 如果你想导出 Cobalt Strike 的数据,通过 Reporting → Export Data 。Cobalt S…

calayer 与uiview

研究Core Animation已经有段时间了,关于Core Animation,网上没什么好的介绍。苹果网站上有篇专门的总结性介绍,但是似乎原理性的东西不多,看得人云山雾罩,感觉,写那篇东西的人,其实是假 设读的人…

代换-置换网络(SP网络)

0x01 概述 代换-置换网络是一系列被应用于分组密码中相关的数学运算,高级加密标准(英语:AES)、3-Way、Kuznyechik、PRESENT、SAFER、SHARK、Square都有涉用。这种加密网络使用明文块和密钥块作为输入,并通过交错的若干…

【贪心】最小生成树Kruskal算法Python实现

文章目录 [toc]问题描述最小生成树的性质证明 Kruskal算法时间复杂性Python实现 个人主页:丷从心 系列专栏:贪心算法 问题描述 设 G ( V , E ) G (V , E) G(V,E)是无向连通带权图, E E E中每条边 ( v , w ) (v , w) (v,w)的权为 c [ v ] …

HTML5 学习笔记

HTML5 学习笔记 前言 该学习笔记的相关学习视频:【狂神说Java】HTML5完整教学通俗易懂 目前笔记只有简单的例子和框架,将来在实践中会进一步学习和补充内容 目录HTML5 学习笔记前言网页基本信息网页基本标签标题标签段落标签换行标签水平线标签字体样式…

保护机制

0x01 概述 操作系统提供了许多安全机制来尝试降低或阻止缓冲区溢出攻击带来的安全风险,包括DEP、ASLR等。在编写漏洞利用代码的时候,需要特别注意目标进程是否开启了DEP(Linux下对应NX)、ASLR(Linux下对应PIE&#xf…

机器学习降维算法一:PCA(主成分分析算法)

引言: 机器学习领域中所谓的降维就是指采用某种映射方法,将原高维空间中的数据点映射到低维度的空间中。降维的本质是学习一个映射函数 f : x->y,其中x是原始数据点的表达,目前最多使用向量表达形式。 y是数据点映射后的低维向…

VS 2005模板丢失找回的办法

安装其他插件的时候,常常模板丢失,比较郁闷,以前就用土办法,重装VS来解决这个问题,这次终于弄清楚怎么回事了,可以采取下面两个步骤解决1。复制ProjectTemplates和ItemTemplates,保证VS能找到相…

一个简单的pwn例子---read函数

内容&#xff1a; #include<stdio.h> void exploit() {system("/bin/sh"); } void func() {char str[0x20];read(0, str, 0x50); } int main() {func();return 0; }我们要做的是利用溢出执行exploit函数 分析&#xff1a; 先执行func函数&#xff0c;func函数…

万网与阿里巴巴业务关系图解

阿里巴巴在港上市公司今天发布公告称&#xff0c;计划分拆旗下中国万网赴美上市。那么万网与阿里巴巴其它业务是怎样个关系&#xff1f;且看我们分析。 随着传统企业大面积地转向互联网经营&#xff0c;用电子商务来服务客户&#xff0c;它们面临的第一个问题就是建站。针对这一…

cobalt strick 4.0 系列教程(4)---监听器和基础设施管理

0x01 概述 任何行动的第一步都是建立基础设施。就 Cobalt Strike 而言&#xff0c;基础设施由一个或多个团队服务器、重定向器以及指向你的团队服务器和重定向器的 DNS 记录组成。一旦团队服务器启动并运行&#xff0c;你将需要连接到它并将其配置为接收来自受害系统的连接。监…

【竞赛题解】Codeforces Round #710 (Div. 3)

B. Partial Replacement 题意&#xff1a;有字符串由.和*组成&#xff0c;可标记其中*&#xff0c;首尾的*必须被标记&#xff0c;使被标记的*之间距离不超过k&#xff0c;求最少的标记量 思路&#xff1a;首先从首尾出发确定首尾*的位置&#xff0c;再由首beg出发向后的k个元…

基于RBAC模型的通用企业权限管理系统

1. 为什么我们需要基于RBAC模型的通用企业权限管理系统 管理信息系统是一个复杂的人机交互系统&#xff0c;其中每个具体环节都可能受到安全威胁。构建强健的权限管理系统&#xff0c;保证管理信息系统的安全性是十分重要的。权限管理系统是管理信息系统中代码重用性最高的模块…

密码学加密算法分类_密码学中的国际数据加密算法(IDEA)

密码学加密算法分类Introduction 介绍 International Data Encryption Algorithm (IDEA) is a type of cryptography as a block cipher algorithm designed by "Xuejia Lai" and "James L.Massey" of ETH-Zrich and was first published in the 1991 yea…

如何定位溢出点位置

程序&#xff1a; #include <stdio.h> void exploit() {system("/bin/sh"); } void func() {char str[20];read(0,str,50);printf("the str is:%s\n",str); } int main() {func();return 0; }关掉保护机制&#xff1a; gcc -no-pie -fno-stack-pro…

【竞赛题解】2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛)

B 找山坡 题意&#xff1a;在数组中找到两相等元素相距最大的距离且这两元素间的元素都不小于该两端值 思路&#xff1a;采用单调栈 例如&#xff1a;a[] { 2 3 5 4 6 3 }&#xff0c;栈内存储元素的坐标&#xff08;从1开始&#xff09;&#xff0c;便于计算距离 首先将a[…