学习笔记

高级指针

指针即内存地址 
内存地址: 4G虛拟内存 编号0-4G    0x0000 0000 - 0xffffffff
指针变量: 保存内存地址的变量
*内存地址    取值
&变量        取址

定义指针变量:
类型 *p;    类型:p存储的地址上存储的数据类型
int *p;        int* 是指针的类型       int是指p存储的地址,那片地址上的数据类型

指针算术运算:
	p+1; p++;
	指针+1,加了单位长度的内存地址
	
NULL  悬空指针  
野指针
万能指针  void*

指针与数组:
	int arr[5];
	int *p = arr;  arr ==  &*arr == &*(arr+0) == &arr[0]
	一维数组名其实就是数组首元素的地址  
	数组名和普通的指针的区别在于 数组名不能作为左值
	p[1]    *(p+1)   arr[1]  *(arr+1)
	&arr  数组的地址
	&arr 和 arr 值相同 但类型不同
	arr+1   偏移了一个数组元素的长度
	&arr+1  偏移了整个数组的长度
	int (*parr)[5] = &arr;
	数组指针: 本质是一个指针  该指针指向一个数组
		T (*pname)[n];
		数组指针pname指向一个一维数组  数组长度为n  数组中存储的元素类型为T
	指针数组: 本质是一个数组  数组中的元素为指针
		T * arr[n];    数组中所有元素的类型为  T*
	
	二维数组与指针:
		int arr[3][4] = {};
		int (*parr)[4] = arr == &*arr == &*(arr+0) ==  &arr[0]
			arr   -->  func(int (*parr)[4])  func(int arr[][4])
		parr == arr == &arr[0]
		*parr == *arr == *&arr[0]  == arr[0]  ==  &arr[0][0]
		**parr ==  **arr  ==  *arr[0]  ==  arr[0][0]
		int *p = arr[0]  ==  &*arr[0]  == &*(arr[0]+0)   == &arr[0][0]
		*(*(arr+1)+2) === arr[1][2]
		int (*pa)[3][4] = &arr;

函数与指针:
	函数名即内存地址
	函数指针:  本质是指针  该指针指向一个函数
		T (*pname)(ARGS,...);
		函数指针pname 指向一个函数 该函数返回值类型为T,参数为ARGS  
		int * func(int *p){}
		int * (*pf)(int *);   //pf是一个函数指针变量
		pf = func;
		int a = 0;
		pf(&a);  //调用函数
	typedef T (*PF)(ARGS...);   //给函数指针类型取别名  PF
	PF pf;
	PF arr[5];//函数指针数组
	void (*pf[5])(void); //函数指针数组
	
   #include <signal.h>
   typedef void (*sighandler_t)(int);
   sighandler_t signal(int signum, sighandler_t handler);

	指针函数:  本质是函数  函数返回一个指针类型

定义一个指针函数指针数组变量:
	T* (*parr[n])(...)

	T* (*parr[n])(...);
		是数组  是指针数组  是指针函数指针数组  
	看定义识标识符是什么?
	首先拿到标识符 parr  从标识符往后结合
	 如果是 [  是数组
	 如果是 (  是函数
	 如果是 ) 则往前结合
	     如果是  *  是指针
	然后把上面结合的内容看作一个整体重复上面的动作

int compAsc(int x,int y){
return x-y;
}
int compDesc(int x,int y){
return y-x;
}

void sort(int arr[],size_t n){
int i,j;
for(i=1;i<n;i++){
int key = arr[i];
//for(j=i-1;j>=0&&arr[j]>key;–j){
//for(j=i-1;j>=0&&arr[j]-key>0;–j){
//for(j=i-1;j>=0&&compAsc(arr[j],key)>0;–j){
//for(j=i-1;j>=0&&arr[j]<key;–j){
//for(j=i-1;j>=0&&key-arr[j]>0;–j){
//for(j=i-1;j>=0&&compAsc(key,arr[j])>0;–j){
for(j=i-1;j>=0&&compDesc(arr[j],key)>0;–j){
arr[j+1] = arr[j];
}
arr[j+1] = key;
}
}

文件操作

数据的持久化
打开文件进行读写操作 关闭文件
程序启动时把数据从文件中加载(load)进来
程序退出时把数据从内存中保存(dump)到文件中

FILE *fopen(const char *path, const char *mode);
	失败返回NULL  成功返回FILE* 用于读写文件时传递的参数
	path: 文件路径    "a.txt"  默认是当前目录
	mode: 模式    
	r   Open  text  file  for  reading.  The stream is positioned 
	    at the beginning of the file.

	r+  Open for reading and writing.   The  stream  is
        positioned at the beginning of the file.
		
		如果文件不存在,则失败
		
	w   Truncate  file  to  zero  length or create text
        file for writing.  The stream is positioned  at
        the beginning of the file.

	w+  Open for reading and writing.  The file is created 
		if it does  not  exist,  otherwise it is truncated.
		The  stream  is  positioned at the  beginning of the file.
	
		如果文件存在,则清空
	
	rw+ reading and writing 保留内容
	
	a   Open for appending (writing at  end  of  file).
        The  file is created if it does not exist.  The
        stream is positioned at the end of the file.

	a+  Open for reading and appending (writing at  end
         of  file).   The file is created if it does not
         exist.  The initial file position  for  reading
         is  at the beginning of the file, but output is
         always appended to the end of the file.

	b:  以二进制的形式读写 
		以文本形式读写
	二进制模式和文本模式在linux下无区别
	在windows有区别:  在换行时有区别  python
		
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
	size: 期望每次读取数据的字节数
	nmemb: 期望读多少次

size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
	返回成功写入的个数  与nmemb有关
	返回0表示写入失败
	
数据以什么样的方式写入到文件,那么请以什么样的方式读取出来
	

int fscanf(FILE *stream, const char *format, ...);//从文件中格式输入
int fprintf(FILE *stream, const char *format, ...);//格式化输出到文件
int fgetc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
int getc(FILE *stream);	
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int putc(int c, FILE *stream);

int fseek(FILE *stream, long offset, int whence);//设置文件读写位置
	offset: 偏移的字节数 可正可负   正表示向关  负表示向文件末尾偏移
	whence: 参考位置
		SEEK_SET  文件开始位置
		SEEK_CUR  当前位置
		SEEK_END  文件末尾位置
long ftell(FILE *stream);  获得文件读写位置  距离文件开始位置的字节数
void rewind(FILE *stream);  把读写位置调整到文件开始位置
int fclose(FILE *fp);

练习:
实现cp命令的功能
文件复制
a.out srcpath destpath

写一个函数,计算一个文件的大小!
long filesize(const char *path){
	if(path==NULL){
		return -1;
	}
	FILE *fp = fopen(path,"r");
	if(fp == NULL){
		return -2;
	}
	fseek(fp,0,SEEK_END);//放到文件末尾
	long size = ftell(fp);
	fclose(fp);
	return size;
}

fseek(fp,10,SEEK_END);//不会占内存大小  形成的文件空洞  ftell可以得到偏移值

读写文件时会有一个文件指针位置,即文件读写的位置
这个位置很重要!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值