本文目录
- 一、指针
1.指针的定义
2.指针的声明
3.指针初始化
4.指针的类型
5.指向指针的内容
6.指针的运算- 二、指针与数组
- 三、指针与函数
- 四、动态内存分配
- 五、文件读写操作
- 六、结构体
一、指针
1.指针的定义
- 指针是一个变量
- 指针只能存地址
- 指针占据8个字
总结:指针是一种保存变量地址的变量
int main()
{
int *a;
char *b;
printf("a的大小:%d\n,sizeof(a));
printf("a的地址:%p\n,a);
}
输出结果:
a的大小:8;
a的地址:0x100;
2.指针的声明
以下为几个指针声明的例子
int *p; //指向整型变量的指针变量,用来存放整型变量的地址
int a[5]; int *q = a; //指向数组第0个元素的指针变量
//分析:int a[5],有五个元素,分别是变量 a[0]、 a[1]、 a[2]、 a[3]、 a[4],且a代表的是第0个元素(变量a[0])的起始地址。而变量a[0]的类型是int,所以int *p =a; 是合法的。
char *string = "hello"; //指向字符串的指针变量,string 是一个指针变量,用来存放字符串的首地址,而"hello"返回字符串的首地址
int (*foo)(int x, int y); //指向函数的指针变量 函数指针
//分析:
//int (*foo)(int x, int y) 中foo是一个指针变量,那又是怎样的指针变量呢?再看接下来加粗部分:
//int (*foo)(int x, int y); 这说明foo是一个指向函数(该函数有两个int类型的形参,且返回int 类型的数据)的指针变量
struct student *boy; //指向结构体的指针变量
- 指针的声明相当于普通变量的声明多了一个一元运算符“ * ”。
- 运算符“ * ”是间接寻找地址或者间接引用运算符。当它作用于指针时,将访问指针所指向的对象。
- p 是一个指针,保存着一个地址,该地址指向内存中的一个变量;*p则会访问这个地址所指向的变量。
- 声明一个指针变量并不会自动分配任何内存
- 在对指针进行简介访问之前,指针必须进行初始话:或者使他指向现有的内存,或者给他动态分配内存,否则这个指针会变成野指针(指向未知地址)
3. 指针初始化
/* 方法1:使指针指向现有的内存 */
int x = 1;
int *p = &x; // 指针 p 被初始化,指向变量 x ,其中取地址符 & 用于产生操作数内存地址
/* 方法2:动态分配内存给指针 */
int *p;
p = (int *)malloc(sizeof(int) * 10); // malloc 函数用于动态分配内存
free(p); // free 函数用于释放一块已经分配的内存,常与 malloc 函数一起使用,要使用这两个函数需要头文件 stdlib.h
4.指针的类型
去掉星号* 和变量名 就是指针的类型
int *p ; char p ; int (func)(int );
指针变量只能指向同种数据类型的地址
NULL 空指针,表示不指向任何东西。可以通过给一个指针赋一个零值来生成一个 NULL 指针
常量指针: 可以改变指针的指向
int a = 20;
int const *pa = &a; const -> 不变的量
pa = &b;指针常量: 可以改变指针指向的变量的值
int b = 30;
int * const pb = &b;
*pb = 50;指向常量的常量指针:啥都不能变 就是被定义的一个常量
int const * const pc = &a;
5.指针指向的内容
- 指针存储的内容为变量的地址,也就是说指针的是一个指向作用,只想变量所存储的内容
- 通过 *指针名 来访问指针指向地址里面的内容
int main()
{
int a = 5;
int *p = &a;
printf("%d",*p);
//输出 5 ;
}
6.指针的运算
C 指针的算术运算只限于两种形式:
-
指针 +/- 整数 :
可以对指针变量 p 进行 p++、p--、p + i 等操作,所得结果也是一个指针,只是指针所指向的内存地址相比于 p 所指的内存地址前进或者后退了 i 个操作数。用一张图来说明一下:
在上图中,10000000等是内存地址的十六进制表示(数值是假定的),p 是一个 int 类型的指针,指向内存地址 0x10000008 处。则 p++ 将指向与 p 相邻的下一个内存地址,由于 int 型数据占 4 个字节,因此 p++ 所指的内存地址为 1000000b。其余类推。不过要注意的是,这种运算并不会改变指针变量 p 自身的地址,只是改变了它所指向的地址。
指针 - 指针
只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针。两个指针相减的结果的类型是 ptrdiff_t,它是一种有符号整数类型。减法运算的值是两个指针在内存中的距离(以数组元素的长度为单位,而不是以字节为单位),因为减法运算的结果将除以数组元素类型的长度。举个例子:
#include "stdio.h"
int main(){
int a[10] = {1,2,3,4,5,6,7,8,9,0};
int sub;
int *p1 = &a[2];
int *p2 = &a[8];
sub = p2-p1;
printf("%d\n",sub); // 输出结果为 6
return 0;
}
二、指针与数组
数组指针(也称行指针)
定义 int (p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。
如要将二维数组赋给一指针,应这样赋值:
int a[3][4];
int (p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
p++; //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]
所以数组指针也称指向一维数组的指针,亦称行指针。指针数组
是数组,每一个元素都是指针
定义 int p[n];
[]优先级高,先与p结合成为一个数组,再由int说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1时,则p指向下一个数组元素,这样赋值是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 p=a; 这里p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针
for(i=0;i<3;i++)
p[i]=a[i]
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
所以要分别赋值。这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。
还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
比如要表示数组中i行j列一个元素:
(p[i]+j)、((p+i)+j)、((p+i))[j]、p[i][j]优先级:()>[]>*
三、指针与函数
(一) 指针函数
- 指针函数是一个函数,只不过指针函数返回的类型是某一类型的指针。
- 格式:类型名* 函数名(函数参数列表)
- 实际运用:
/*
* 指针函数,返回int* 指针变量
*/
int* add(int a, int b)
{
int *p;
int c = a + b;
p = &c;
return p;
}
int main()
{
int* p;
p = add(1, 4);
printf("%d\n", *p);
getchar();
return 1;
}
(二)函数指针
- 函数指针是指向函数的指针变量。所以函数指针其实是指针变量,只不过该指针变量指向函数。
- 格式:类型名 (*指针变量名) (函数参数列表)
- 函数指针的用途:
a.调用函数
b.做函数的参数 - 调用函数:
/*
* 函数指针,调用函数
*/
int fun1(int a, int b)
{
return a + b;
}
int main()
{
int(*p)(int, int);
p = fun1;
printf("%d\n", p(1, 5));
getchar();
return 0;
}
- 做函数的参数:
/*
* 函数指针,最为参数
*/
int fun2(int a, int b)
{
return a + b;
}
int fun3(int a, int b, int(*f)(int, int))
{
return f(a, b);
}
int main()
{
printf("%d\n", fun3(1, 5, fun2));
getchar();
return 1;
}
四、动态内存分配
为什么需要动态内存分配:
1.存储的数据 需要延长生命周期
2.一个指针变量需要存储数据,变量本身只能存地址,不能存数据,需要分配内存空间来存储数据如何分配:
malloc 申请内存 realloc 重新申请内存
name = (char)malloc(name,20sizeof(char));
int main()
{
//如果使用指针变量接收数据
//必须先为这个指针变量分配一片指向的内存空间
//有内存空间 才能存数据
//导入头文件stdlib.h
//使用 malloc (memory allloc)申请内存空间
char *name;
name = (char*)malloc(10*sizeof(char)); //分配内存
if(name == NULL){
// 申请内存失败
exit(EXIT_FAILURE);
}
scanf("%s",name);
printf("%s\n",name);
//使用realloc动态改变内存的大小——增加或减少
name = (char*)realloc(name,20*sizeof(char));
if(name == NULL){
// 申请内存失败 退出之前必须将之前分配的内存释放掉
free(name);
exit(EXIT_FAILURE);
}
free(name);
return 0;
}
五、文件读写操作**
- 打开文件
c语言使用fopen()函数来打开一个已存在的文件或者创建一个新的文件;
函数调用原型:
FILE *fopen( const char * filename, const char * mode );
其中,filename是字符串,用来命名文件,访问模式 mode 的值可以是下列值中的一个:- 关闭文件
c语言使用fclose()函数来关闭文件;
函数调用原型为:
int fclose( FILE *fp );
文件关闭成功,函数返回0,关闭失败返回EOF。(EOF为定义在<stdio.h>中的常量)
- 写入文件
c语言使用fputc()函数将字符写入流;
函数原型为:
int fputc( int c, FILE *fp );
如果是字符串则用:
int fputs( const char *s, FILE *fp );
写入成功返回一个非负值,失败返回EOF。
使用 int fprintf(FILE *fp,const char *format, ...) 函数来写把一个字符串写入到文件中。
- 读取文件
c语言使用fgetc()函数将字符写入流;
函数原型为:
int fgetc( FILE * fp );
如果是字符串则用:
char *fgets( char *buf, int n, FILE *fp );
函数 fgets() 从 fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串。
如果这个函数在读取最后一个字符之前就遇到一个换行符 '\n' 或文件的末尾 EOF,则只会返回读取到的字符,包括换行符。
使用int fscanf(FILE *fp, const char *format, ...) 函数来从文件中读取字符串,但是在遇到第一个空格字符时,它会停止读取。
————————————————。
出自:https://blog.csdn.net/zztingfeng/article/details/82287974
六、结构体
结构体:
int float 只能存单个数据
int num[] 可以存多个数据 必须同种类型
学生:学号long long 年龄 int 姓名 char*为什么使用结构体:
需要一种类型,这种类型可以保存多种数据结构体是什么:
一种类型如何定义结构体类型:
注意定义结构体类型 内部类型不能赋储至
struct student
{
int age;
char sex;
char name[10];
}如何使用:
int a = 10;
struct student xw;
struct student lw = {40,'m',"隔壁老王"};使用结构体变量:
lw.age = 35;
int main()
{ //定义结构体类型
struct person{
int age;
float height;
};
//定义变量
struct person xw;
xw = {33,88.8};
struct person *p;
p = &xw;
cout<<xw.age<<endl;
//指针使用->访问元素
p->age = 30;
cout<<xw.age<<endl;
//将结构体保存到文件
//打开文件
FILE *fp = fopen("C:/Users/53573/Desktop/test1.txt","a+");
//将小王写入文件
//fwrite(&xw,sizeof(struct person),1,fp);
//读取内容
struct person zs;
fread(&zs,sizeof(struct person),1,fp);
struct person *p1 = &zs;
p1->height = 180.88;
printf("age:%d height:%f\n",zs.age,zs.height);
return 0;
}