1.3 C语言--指针与结构体
指针
指针概念的引入
- 关于内存
程序有数据和指令组成,数据和指令在执行过程中存放在内存中。变量是程序数据中的一种,因此变量也存储在内存中;内存中的每个字节都有一个唯一的编码,即内存地址。32位机的内存地址编码是32位的(所以32的内存最多4G),64位机的内存地址编码是64位的。地址是一个无符号的整数,从0开始递增,通常把地址写成十六进制数。地址的长度跟主机的字长相同。
- 关于变量的寻址
- 直接寻址(通过地址直接访问值)
直接到变量名标识的存储单元中读取变量的值。最常见的就是scanf函数,scanf("%d",&a),这里的&表示取地址,是将获取到的值存储到a这个地址里面。如果我们这里不写&取地址运算符,获取的就是a的地址(?为什么直接写a,获取的是a的地址,&a是取a地址,这个不是相互矛盾吗?)
- 间接寻址
通过其他变量间接的找到变量的地址,最常用的就是指针。指针类型就是指向变量的地址。
- 变量在内存中所占存储空间的首地址,称为变量的地址;变量在存储空间的数据,称为数据的值;变量的名称可以看成是对程序中存储空间的抽象;声明一个变量实际上是记住这个变量的首地址和该数据类型的长度。
- 变量名通常是首地址和长度的统一,可以理解是一种映射
- 而&(取地址运算)是取的该变量的首地址。
- 指针的定义
int *pa; // 定义语句 表示pa保存的是一个int数据类型的地址(不要理解成地址是一个int类型的,表明首地址,并说明数据类型(推断出长度))
int *pa = &a; // 初始化,也可以写成int a = 1;pa = &a;因为*pa是一个地址,而&a是取地址。所以两者是可以赋值的。
我们可以吧指针理解为一个软连接的概念。
- 如果将指针理解为java中的包装类,java中的包装类也是通过地址进行访问的
- 指针使用必须被初始化
- int *p = null ; // null是空指针,随便给一个地址。
- 代码分析
# include <stdio.h>
int main(){
int a=0,b=1;
int *pa,*pb;
pa = &a;
pb = &b;
printf("a = %d,b=%d\n",a,b);
printf("*pa=%d,*pb=%d\n",*pa,*pb);
return 0;
}
- 再次关于内存地址
- 我们将的内存地址是逻辑地址,而不是物理地址。就像电流只要联通电线就可以到达一样,计算机访问在物理层面也只是电流的访问而已,根本不需要什么地址。内存地址是方便人理解的逻辑地址,这个可以理解为是电表的编号。
- 所以int a = 10;中的a就是(逻辑)地址(一堆二进制的开关)没错,但是计算机无法理解逻辑地址,对它来说就是按照开关放电,所以直接就是a的值了。
- &a是取(逻辑)地址,就是把这个a物理地址转换成可见逻辑地址,让我们看到
- 指针并不等于内存地址。内存地址声明就无法更改。但是指针可以指向不同的内存逻辑地址。因此指针的指向的地址是可变的。
- *pa一旦指向一个地址,我们访问*pa,就是访问*pa指向的(逻辑)地址,计算机自动将逻辑地址转换成物理地址,所以访问的其实就是*pa逻辑地址所代表的物理值。
- scanf("%d",&a) // 表示将a的地址指向输入的值得地址
指针的定义
定义指针
- 定义与初始化指针
int *a=NULL; // 这里的int表示指针指向的地址是要存放int类型的数据。这里的*表示指针的解引用,a实际是指针指向的地址,而*a表示a指向的内存地址所代表的值;指针必须被初始化,没有初始化的指针是无法使用的。为了防止意外的发生,通常高我们会将指针命名为null。
- 指针的赋值与取值运算
- p=&a // 将a的地址给p;&表示取地址。必须理解的是指针是一种数据类型,专门涌过来存放地址。这跟基本类型的声明很像 int a=10;就是将10这个int类型的数据给变量a.
- prinf("%d",*p); // 这里的*表示指针的解引用,就是说这里不输出p存储的地址,而输出p存储的地址里面存储的值。
- printf("%p",p); // 这里的%p专门用来格式化输出指针里面存储的地址。这里输出的是指针p存储的地址。
指针与变量的区别
- 变量的声明与初始化
int a = 0; // 这里的a只是我们标识某个内存空间的值,是方便我们识别用的。计算机会将a这个标识符映射为逻辑地址,再转换成物理地址,最后输出值的。而*p则是直接访问p所存储的地址的值
- 区别
int a = 0;
int *p = null;
p = &a;
printf("%d",*p);
解释: a表示0这个变量的长度和首地址,&a表示首地址;*p表示首地址和长度,p表示这个int类型的地址存什么值,&p是*p的地址。可以将a理解为抽屉A,p理解为抽屉B,通过指针访问就是抽屉B中放着抽屉A的钥匙.
int a = 10;实际上a也是地址值,只是通过这个地址值能直接访问到该值。而p=&a 就是将a的地址值给p,当我们方位地址p中的地址是,就能通过地址获地址代表的值。
指针的用处
指针存在的意义就是为了间接引用
#include <stdio.h>
main(){
// int *p = 10; // *p 接收的只能是地址
int a = 10;
// int *p = a; // 这句话是错误的。
int *p = &a;
printf("p is %d\n",p);
printf("*p is %d\n",*p);
printf("&p is %d\n",&p);
}
必备代码:如何使用指针交换连个值。
#include <stdio.h>
void swap(int *a,int *b);
/*
* 使用指针交换用户输入的两个数据
*/
void main() {
int a,b;
printf("Please type two number value of a,b:\n");
scanf("%d,%d",&a,&b);
printf("before swap,the value of a is %d,the value of b is %d.\n",a,b);
swap(&a,&b);
printf("after swap,the value of a is %d,the value of b is %d.\n",a,b);
}
/*
* 始终不是很明白为什么这里使用int middle 来接收指针*/
void swap(int *a,int *b) {
int middle ;
middle = *a;
printf("%d",*middle);
*a = *b;
*b = middle;
}
- 结构体与共用体
- 结构体
- 什么是结构体
- 可以理解为java中的类,即只有成员变量没有成员方法的类。
- 结构体的声明与使用
- 声明格式(尤其注意几处分号)
struct 结构体名称{
数据类型 成员变量名称;
……
};
- 具体的声明,赋值与调用
#include <stdio.h>
struct student{
int age;
int class;
int score[3];
};
void main(){
// 初始化并赋值方式之一:
struct student stu1;
stu1.age=10;
stu1.class=1;
// stu1.socre[] = {11,22,33}; // 这种赋值错误的,反正我也不知道为什么
stu1.score[0]=11;
stu1.score[1]=22;
stu1.score[2]=33;
// 初始化并赋值方式之二
/* struct student stu2;
stu2 = {10,1,{11,22,33}}; // 这种赋值方式是错误的 */
struct student stu2 ={10,1,{11,22,33}};
printf("This is content of student struct:\n");
printf("student age is : %d\n",stu1.age);
for(int i=0;i<3;i++){
printf("student's score:%d\n",stu1.score[i]);
}
}
- 各种使用方式
- 使用typedef定义数据类型
- typedef本质上只是一个已有数据类型定义别名的东西。主要是为了声明时节省一个关键字而已。
#include <stdio.h>
void main(){
/*
* 定义一个结构体
* 使用typedef 关键字,将student的别名设置为了STUDENT
* 这样的话在声明结构体时就可以省掉一个struct关键字*/
typedef struct student{
int age=10;
char name[10];
}STUDENT;
// 声明一个结构体
STUDENT st1={1,{'h','u','a','b','i','n'}};
}
- 结构体的声明
- 方式一: 结构体别名 具体结构体名;
- 方式二:struct 结构体名 具体结构体名;
- 结构体的赋值
- 方式一:struct student stu2 ={10,1,{11,22,33}};
- 方式二:stu1.score[0]=11;
- 注意:有两种赋值方式是不允许的
stu1.socre[] = {11,22,33};
- 或者
struct student stu2;
stu2 = {10,1,{11,22,33}};
- 结构体成员变量的使用
- 结构体名.变量名
- 结构体的字节数
- 建议使用typeof()关键字来具体的查看
- 结构体指针
- 结构体是值传递,是不会修改具体的内容的
- 一旦传递指针作为函数的参数,必须使用->来访问成员变量
- 结构体中嵌套结构体
- 使用结构体.结构体.成员变量 来实现访问
1.3 C语言--指针与结构体的更多相关文章
- c语言指针与结构体
#include <stdio.h> #include <stdlib.h> struct mydata { int num; ]; }; void main1() { /*i ...
- c语言指针与结构体之内存动态分配
struct dangdangtest { ]; ]; ]; int num; int bugnum; ]; ]; double RMB; }; void main2() { //struct dan ...
- 数据结构复习之C语言指针与结构体
数据结构指针复习: #include <stdio.h> void main() { ] = {, , , , }; // a[3] == *(3+a) printf(+a)); // a ...
- [todo0211]c语言指针,结构体的疑问
#include <stdio.h> #include <mm_malloc.h> struct ListNode { int val; struct ListNode *ne ...
- Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型
Android For JNI(五)--C语言多级指针,结构体,联合体,枚举,自定义类型 我们的C已经渐渐的步入正轨了,基础过去之后,就是我们的NDK和JNI实战了 一.多级指针 指针的概念我们在前面 ...
- 【学习笔记】【C语言】指向结构体的指针
1.指向结构体的指针的定义 struct Student *p; 2.利用指针访问结构体的成员 1> (*p).成员名称 2> p->成员名称 3.代码 #include < ...
- C语言--- 高级指针2(结构体指针,数组作为函数参数)
一.结构体指针 1. 什么是结构体指针?指向结构体变量的指针 结构体: typedef struct stu{ char name[ ...
- 嵌入式-C语言:通过结构体指针操作结构体内容
#include<stdio.h> #include<string.h> struct Student { char name[32]; int age; int height ...
- 嵌入式-C语言基础:通过结构体指针访问结构体数组
#include<stdio.h> #include<string.h> struct Student { char name[32]; int age; int height ...
- C语言中的结构体
用户自己建立自己的结构体类型 1. 定义和使用结构体变量 (1).结构体的定义 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体. (2).声明一个结构体类型的一般形式为: ...
随机推荐
- SSM框架实现附带信息的文件上传&下载
SSM框架实现附带信息的文件上传&下载 目录 目录 SSM框架实现附带信息的文件上传&下载 目录 技术概述 技术详述 技术使用中遇到的问题和解决过程 总结 参考链接 技术概述 在进 ...
- [Swift]Swift图片显示方式设置,控件UIImageView的contentMode属性设置
contentMode属性是用来设置图片在UIImageView中的显示方式,如:拉伸.居中.填充等. 这里讨论的是UIImageView宽高固定,图片宽高不确定的情况.如社交APP的相册缩略图.手机 ...
- nginx(一) の 入门解析
OSI 模型的前三层 应用层: 每一个应用程序自定义的协议 表示层: 数据的压缩与解压缩.图片的编码与解码 会话层: 会话管理(session) 和 网络验证 .包括断点续传和服务器验证用户登录等.比 ...
- Node.js 源码解读 EventLoop
之前断断续续开发过一些 Node.js 的项目,但只仅限于使用它实现一些功能,没有过多对底层深入的研究.现在因为公司大前端组内的服务端渲染直出.BFF(Backend For Frontend) 等需 ...
- img,video标签禁用鼠标右键功能
场景描述: 在网页中显示图片,当用户右键点击图片时,禁止用户右键操作. 这里会用到一个新属性,即 oncontextmenu. 例如: <img src="图片地址" cla ...
- 【Java学习Day09】Java知识点及面试题微讲
Java知识点及面试题 整数拓展 进制 二进制0b 八进制0 十进制 十六进制0x public class Demo03 { public static void main(String[] arg ...
- golang 实现twitter雪花算法
1 /* 2 * twitter雪花算法golang实现,生成唯一趋势自增id 3 * 保留位:63位 4 * 毫秒时间戳:[62-20]43位,时间范围[1970-01-01 00:00:00.00 ...
- 查看linux 用户
sudo cat /etc/passwd|grep -v nologin|grep -v halt|grep -v shutdown|awk -F":" '{ print $1}' ...
- 关闭win10“快速启动”功能
windows正常运行时间的统计问题 windows任务管理器中,在性能选项卡中可以查看系统的运行时间(开机时间) 正常情况下,如果电脑关机,那么再次开机后,该时间会被重置 但是,如果电脑处于上面所说 ...
- PVD模板
void PVD_Init(void){ EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //--- ...