1 指针

首先看变量在内存中的存储

有时候需要获取并使用程序运行中某个变量的内存地址,如何获取这个地址、如何存储这个地址?

&取地址符,&a就是获得了a的地址

可以存储地址的变量称为指针变量

指针看起来就是地址,但不仅仅是地址信息,还包含类型信息

2 指针变量的声明和初始化

声明指针变量

int  *pn;    //pn 是整型指针,指向整型变量

指针变量名是pn,不是*pn   * 是指针声明符

float *pa;   //pa 是浮点型指针,指向浮点型变量
char *pc;    //pc 是字符型指针,指向字符型变量

声明并初始化指针变量

int  i, *p = &i;

等价于

int  i;
int  *p = &i;

等价于

int  i, *p;
p = &i;

下面看指针和变量在内存中的形式

最好在声明指针时就对它进行初始化。一个指向不确定的指针是很危险的,因为通过指针可以访问其指向的内存区域,会造成意外覆盖内存

如果声明指针变量时不能确定它的指向,可以初始化为NULL

int  *p = NULL;

值为NULL的指针称为空指针,这意味着,指针并不指向任何地址。在头文件 stdio.h 中,NULL 定义为常量0。

3 指针与数据类型

前面关于指针的讨论忽略了一个重要事实,即不同类型的数据在内存中占用的字节数量是不同的。 而指针仅指示了第一个字节的地址。如何通过指针访问该数据:读取多少个字节? 如何理解这些字节内容?

所以编译器必须知道它所指向的数据类型,每个指针都和某个数据类型相关联。

int  *p;          //p指向一个int类型的对象 ,读4个字节
double *p;    //p指向double类型的对象,读8个字节

(1)指针变量也是一个变量,只不过该变量中存储的是另一个对象的内存地址

(2)如果一个变量存储另一个对象的地址,则称该变量指向这个对象

(3)由于指针值是数据,指针变量可以赋值,所以一个指针的指向在程序执行中可以改变。指针p 在执行中某时刻指向变量a,在另一时刻也可以指向变量b

 int a;int *p = &a; // p中存的是a的地址

4 间接访问运算符

直接访问n:通过变量名访问,如 n = 15;

间接访问n:通过另一个变量来访问,pn中存储了n的地址,通过pn可以间接访问n,*pn就是对n的引用

   int  a = 3, *p = NULL;     printf("a的地址:%p\n", &a);    //用格式符%p以十六进制格式输出内存地址。printf("a的值:%d\n", a);p = &a;  //让指针变量p指向a  printf("\np的地址:%p\n", &p);   //变量p也需系统分配内存地址,也有内存地址 printf("p的值:%p\n", p);printf("*p的值:%d\n", *p);*p=10;   //等价于a=10;printf("\na=%d, *p=%d\n", a, *p);   //指针变量p指向a, *p是通过a的地址间接访问a

#include<stdio.h>
int main()
{int a = 1, x, y, *p;p = &a;x = (*p)++;   //即x=a++; 先使用再增1,即x=a; a++;y=*p;printf("x=%d,y=%d\n",x,y);  //x=1,y=2
}

x = (* p)++;
++运算的对象是* p,而不是p
++后置,先使用再增值,
等价于:
x=* p; (*p)++;
将 p 所指向的变量值加1

5 指针作为函数的参数

有了指针的概念,重新思考以下问题:如何在被调函数中改变主调函数的局部变量?

C语言中,参数传递是“传值”方式,形参是实参的副本,因而在被调函数中,对形参的修改不影响实参变量的值。

为达到改变变量的目的,需用指针变量作为函数的形参,将实参变量的指针传给形参。此时,在函数执行过程中,通过形参指针,间接访问被调函数中的变量。

//以下程序不能实现a、b值的互换
void swap(int x, int y)
{int t;t = x;  x = y; y = t;
}
int main()
{int a = 3, b = 5;swap( a, b );printf("%d %d\n",a,b);     // 3 ,5 return 0;
}

形参变量值的改变不会影响实参可以打个比方,main用传真方式把a和b的内容传给了swap,swap接到传真,打印到x和y上,x和y是a和b的副本,x和y的改变不会影响a和b的内容。

试试看:用指针解决问题

void swap( int *pa, int *pb)
{int t;t = *pa; *pa = *pb;  *pb=t;  //*pa是对a的引用,*pb是对b的引用
}
int main()
{int a = 3, b = 5;swap(&a, &b);      // 传递a,b的地址printf("%d %d\n",a,b);    // 5 3return 0;
}

通过形参指针变量pa和pb间接访问并改变了a和b的值打个比方,是main给swap打电话,告诉他a和b这两个原件就在档案柜的第315(存入pa)、316号抽屉(存入pb) ,swap直接去315和316号抽屉,直接访问和修改的是原件a和b

试试看:为何不能实现互换

#include<stdio.h>
void swap( int *pa, int *pb)
{int *t;t = pa;  pa = pb; pb = t;
}
int main()
{int a = 3, b = 5;swap(&a, &b);printf("%d %d\n", a, b);   // 3 5return 0;
}

函数调用结束时,pa,pb被释放, 形参指针变量值的改变不会影响实参

如何访问主调函数中的变量,要通过函数调用来改变主调函数中某个变量的值:
(1) 在主调函数中,将该变量的地址或者指向该变量的指针作为实参
(2) 在被调函数中,用指针类型形参接受该变量的指针
(3) 在被调函数中,用形参指针间接访问主调函数中的变量。

6 结构类型的定义方法

struct 结构体名
{数据类型  成员1名;数据类型  成员2名;….数据类型  成员n名;
};   //;不要漏掉

结构类型变量的定义

常用两种方法:
1 先定义结构体模板,再定义变量名

struct student
{long  stuID;char  stuName[10];char  stuSex;char  birthYear;int     mathScore;
};
struct student stu1;       // stu1是变量

2 在定义类型的同时定义变量

struct student
{long  stuID;char  stuName[10];char  stuSex;char  birthYear;int     mathScore;
}stu1;

7 嵌套的结构类型

在一个结构体内其成员可以是另一个结构体

struct date
{int  year;int  month;int  day;
};
struct student
{long  studentID;char  stuName[10];char  stuSex;struct date  birthday;int     mathScore;
};struct student stu1;

注意:不可以嵌套同类型的结构体

8 使用typedef定义数据类型别名

可以这样写

struct student
{long  stuID;char  stuName[10];char  stuSex;int     mathScore;
};
typedef struct student STUDENT;

也可以

typedef struct student
{long  stuID;char  stuName[10];char  stuSex;int     mathScore;
} STUDENT;

定义后别名和原名通用

struct student stu1;
STUDENT stu2;

9 结构变量的初始化

不嵌套情况

STUDENT  stu2={100010,"King哥",'M',95};
struct student stu1={100010,"King哥",'M',  95};

嵌套情形

STUDENT stu1={100010,"King哥",'M', {2001,7,9}, 95};

10 结构变量成员的引用

typedef struct date
{int  year;int  month;int  day;
}DATE;
struct student
{long  stuID;char  stuName[10];char  stuSex;DATE  birthday;int     mathScore;
} stu1;

圆点运算符
结构体变量名.成员名

stu1.stuID = 100012;

嵌套情形
以级联方式逐级访问

stu1.birthday.year = 1990;

11 结构数组

结构数组定义

元素为结构类型的数组称为结构数组。
在实际应用中,经常用结构数组来表示具有相同数据结构的一个群体。例如一个班的学员档案,一个公司的职工档案等

struct student
{int num;char name[20];char sex;float score;
}stu[30];

定义了一个结构数组stu,共有30个元素,stu[0]~stu[29]。每个数组元素都具有struct student的结构形式

结构数组元素的成员引用
结构体数组名[下标] . 结构体成员名
使用方法与同类型的变量完全相同

 stu[5].num = 26;strcpy(stu[5].name, "Zhang San");stu[4] =stu[1];

12 结构指针

结构指针:指向结构类型变量的指针
结构类型名 *指针变量名

 struct student stu1 = { 1,"СÃ÷",'F',45};struct student *p;p = &stu1;

12 通过结构指针访问结构成员

(1) 用* p访问结构成员

(*p).num = 36;

(2) 用指向运算符“->”访问结构成员。

p->num = 36;

当p = &stu1时,以下三条语句相同:

 p = &stu1;stu1.num = 36;(*p).num = 36;p->num = 36;

结构成员的多种访问方法

#include<iostream>
#include<bits/stdc++.h>
using namespace std;struct employee
{char  name[20];int   age;int   tel;
};
int main( )
{struct  employee emp1 = {"jk", 22,  67896544};struct  employee  *p;p = &emp1; printf("%s,%d,%d\n", emp1.name,  emp1.age,  emp1.tel);printf("%s,%d,%d\n", (*p).name,  (*p).age, (*p).tel);printf("%s,%d,%d\n",  p->name,  p->age,  p->tel);return 0;
}

13 内存分配函数

malloc()——分配内存块,但不对内存块初始化。
calloc()——分配内存块,且对内存块清零。
realloc()——调整先前分配的内存块的大小。

函数返回void *类型的值。void *类型的指针是”通用”指针,本质上只是内存地址。(由于无法知道计划存储在内存块中的数据是什么类型,所以它们不能返回int类型、char类型等普通类型的指针。)

如果内存分配失败返回“空指针”,用宏名”NULL”表示。空指针是“不指向任何地方的指针”

1 动态存储分配函数malloc()

void *malloc(unsigned size)
在内存的动态存储区中分配一连续空间,其长度为size
若申请成功,则返回一个指向所分配内存空间的起始地址的指针
若申请内存空间不成功,则返回NULL(值为0)
返回值类型:(void *)
通用指针的一个重要用途 :将malloc的返回值转换到特定指针类型,赋给一个指针

2 动态存储释放函数free

void free(void *ptr)
释放由动态存储分配函数申请到的整块内存空间,ptr为指向要释放空间的首地址。
当某个动态分配的存储块不再用时,要及时将它释放

3 其它动态存储分配函数

void calloc(unsigned n, unsigned size)
calloc函数为n个元素的数组分配内存,其中,每个元素长度都是size个字节。(calloc与malloc类似,但是主要的区别是存储在已分配的内存空间中的值默认为0,使用malloc时,已分配的内存中可以是任意的值。)
void * realloc(void
ptr, unsigned size)
调整先前分配的内存块的大小, ptr指向原先通过malloc、calloc或realloc获得的内存块,size是内存块的新尺寸

 p = (int *) malloc (n* sizeof(int)); p = (int *) calloc (n, sizeof(int)); p = (int *) realloc (p, n*sizeof(int));

数据结构-指针和结构体相关推荐

  1. C语言指针与结构体详述

    C语言指针与结构体详述 前言 一.数组概述 1.1 一维数组 1.2 二维数组 1.3 多维数组 二.字符数组和字符串 2.1 字符数组 2.2 字符串 2.3 字符串函数 2.4 拓展字符串函数 三 ...

  2. C语言结构体与指针ppt,c语言指针和结构体:链表详解.ppt

    c语言指针和结构体:链表详解.ppt 1,第十一章 链表,2,例跳马.依下图将每一步跳马之后的位置x,y放到一个"结点"里,再用"链子穿起来",形成一条链,相邻 ...

  3. c语言指针和结构体难点,C语言指针和结构体

    第一章 指针 知识点1. a. 函数内的局部变量存在了STACK,全球变量存在了GLOBALS. b. 指针和变量一样,内容是地址 c. *variable = address d. &add ...

  4. 【黑马程序员 C++教程从0到1入门编程】【笔记1】数据类型、运算符、程序流程结构、数组、函数、指针、结构体

    黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难 文章目录 1.C++初识 1.1 第一个c++程序 1.2 注释 1.3 变量 1.4 常量 1.5 关键字 1.6 标识符命名规则 2 ...

  5. C++阶段01笔记汇总【C++软件安装、C++初识、数据类型、运算符、程序流程结构、数组、函数、指针、结构体】

    C++| 匠心之作 从0到1入门学编程[视频+课件+笔记+源码] 目录 C++课程安排 1 C++初识 1.1 第一个C++程序 1.1.1 创建项目 1.1.2 创建文件 1.1.3 编写代码 1. ...

  6. new 结构体指针_Go:我应该用指针替代结构体的副本吗?

    logo 对于许多 golang 开发者来说,考虑到性能,最佳实践是系统地使用指针而非结构体副本. 我们将回顾两个用例,来理解使用指针而非结构体副本的影响. 1. 数据分配密集型 让我们举一个简单的例 ...

  7. Golang——指针的使用、数组指针和指针数组、指针与切片、指针与结构体、多级指针

    指针: 指针是一个特殊的变量,因为存储的数据不仅仅是一个普通的数据,而是一个变量的内存地址,指针本身也是有内存地址的 指针的数据类型有int.float.bool.string.数组.结构体 指针的作 ...

  8. C语言 指针与结构体

    结构体指针 # include <stdio.h>//引用函数库 # include <stdlib.h> struct info{char name[4];int age; ...

  9. C语言基础1:初识C语言(转义、注释;数组、操作符、反码、补码、static、define、指针、结构体常变量;局部变量;作用域、生命周期)

    文章目录 C语言基础1:初识C语言 1.C语言简介 1.1什么是C语言 1.2C语言的发展 2.第一个C语言程序 2.1创建项目 2.2添加源文件 2.3写代码 3.数据类型 4.变量.常量 4.1定 ...

  10. C语言实现简单的图书馆小程序(练习指针和结构体的基本使用)

      放弃不难,但坚持一定很酷.   目的:练习指针和结构体的基本使用.   题目:构建一个"图书馆"小程序(library),让用户将书籍的基本信息都录入到里面,最后一并打印出录入 ...

最新文章

  1. ubuntu 12.04.1升级至ubuntu 12.10出现gcc-4.7依赖库错误的解决办法
  2. UIView上的控件使用push方法跳转
  3. Matplotlib实例教程(七)密度图
  4. 软工三(5.12上课)
  5. 【RabbitMQ】一文带你搞定RabbitMQ延迟队列
  6. 利用 IHttpHandler 自定义 HTTP 处理程序
  7. 宿迁学计算机的学校,宿迁计算机学校
  8. c 语言开发一个四则运算器,C++实现四则运算器(无括号)
  9. C# 打开文件 保存文件
  10. 解析Linux内核的基本的模块管理与时间管理操作---超时处理【转】
  11. Windows Azure 客户真实案例:交互式解决方案提供商获得了敏捷性,通过托管服务节省了成本...
  12. java 字符串长度_ava练习实例:java字符串长度与Java String charAt() 方法 (建议收藏)...
  13. thinkphp5实战系列(二)前台模板的引入
  14. CSDN日报20170224——《程序员该用哪种姿势来理财》
  15. Java - Log
  16. 获取非行内样式的兼容
  17. Swift语言针对机器学习
  18. VS2010启动后鼠标失灵解决方法
  19. 淘宝UWP PC版邀请码已经发放给了前20名申请的博友。请在你们的博客园私信里查收。...
  20. 论文解读:学习蛋白质的空间结构可以提高蛋白质相互作用的预测

热门文章

  1. 计算机网页外文文献图书,免费外文文献网站.doc
  2. 服务器固件测试--PCI设备的介绍(集成网卡和外插网卡)
  3. 爱荷华州立大学计算机科学,爱荷华州立大学计算机科学硕士排名第64(2020年TFE Times排名)...
  4. 人像抠图处理百度API接口调用
  5. JAVA高级工程师知识树
  6. 解决CSDN无法复制
  7. 使用EasyUI固定表格的行或列
  8. win10系统如何查询本机的IP地址和外网IP地址
  9. 进程间通信-消息机制
  10. ZOJ 4093 浙大校赛D题 Robot Cleaner II(思维+构造题)