C语言之指针二

函数指针

如果在程序定义了一个函数,在编译时,编译系统为函数代码分配一段存储空间,这段存储空间的起始地址,称为这个函数的指针 

函数名就是函数开始的地址


函数二级指针可以修改函数指针的指向


函数指针,不仅仅是地址,必须明确函数指针类型和输出参数类型和数量
函数名可以作为参数传递给函数指针

#include <stdio.h>
#include <stdlib.h>

int add(int a, int b)
{
	return a + b;
}

void print()
{
	printf("你好,明天\n");
}

int main()
{
	printf("%p %p\n", add, print);

	void(*p)() = print;     //声明函数指针,并初始化函数指针
	int(*pa)(int a, int b) = add;	//声明函数指针,并初始化函数指针
									//初始化指针只能传递地址

	print();			//直接调用
	p();				//调用函数指针,相当于调用函数,间接调用

	printf("%d\n",pa(12,36));

	system("pause");
}


函数的返回值可以是指针

#include <stdio.h>
#include <stdlib.h>
#include<time.h>

//函数,返回一个地址,对于数组而言,函数参数调用没有副本机制
//函数返回值是一个指针类型的函数
int* mindata(int a[], int n)		//查找最小数 
{
	int *p = NULL;	//声明指针变量,指向空指针,最后保存最小值的地址
	int min = a[0];
	p = &a[0];
	for (int i = 1; i < n; i++)  //选择法
	{
		if (min > a[i])
		{
			min = a[i];
			p = &a[i];
		}
	}
	printf("最小的值为%d\n",*p);
	return p;			//返回最小值的地址
}

int main()
{
	int a[10];
	time_t ts;
	srand((unsigned int)time(&ts));	 //按照时间设置随机数种子
	for (int i = 0; i < 10; i++)
	{
		a[i] = rand() % 100;
		printf("%d\n",a[i]);
	}

	int *p = mindata(a,10);  //获取最小数的地址

	//此时 直接修改*p 可以起到修改最小值  如,*p = 35;
	printf("%d\n",p -a);   //可以知道下标符号

	system("pause");
}

左值,能放在赋值号左边的值
int *const px;   //指针常量


写一个和strcpy函数功能相同的函数

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//写一个和strcpy函数功能相同的函数
char* mystrcpy(char* dest, char* source)  //两个参数目的 ,来源
{
	char * last = NULL;			//最后结果
	if (dest == NULL || source == NULL)
	{
		return last;    //如果传入的两个字符串有一个是指向空指针的,结束函数
	}
	last = dest;//存入首地址
	while ((*dest++  = *source++) != '\0');
									//没有遇到字符 '/0',一直拷贝数据
	return last;
}

int main()
{
	char str[40] = {0};

	//char * p = mystrcpy(str, "你好明天\n");		//声明一个指针接受字符串str的首地址
	//printf("%p %p\n",str,p);				地址相同
	//printf("%s", p);
	//printf("地址为%p\n", strcpy(str, "你好明天\n"));//strcpy函数返回字符串str的地址


	printf("%s", strcpy(str, "山阴路的夏天\n"));    //两条语句的作用相同,函数没有问题
	printf("%s", mystrcpy(str, "你好明天\n"));    //两条语句的作用相同,函数没有问题
	
	system("pause");
}


指针包括 类型和地址,将地址转换为指针,需要进行类型的转换
如:
int* p;
int x;
scanf("%x",&x);
p = (int*) x;   //将地址转换为指针
 
void指针和空指针
void* 类型的指针,只包含地址不包含类型,是不指向任何类型的指针,任何类型都可以赋值给空类型指针,纯地址的赋值,但指向不明确,大小不确定,无法取出内容,如果需要取读地址的内容
应先对地址进行类型的转换,一般用于参数还有返回值,不明确指针类型的情况传递地址,如  malloc() 函数的返回值


int* p =NULL;//不指向任何地址,即没有初始化,空指针,*p等价于int类型,p等价于int*类型


void *p = malloc(20); //分配20个字节的内存,返回值赋值给void*类型指针变量p,可以转换成任何类型的指针,malloc函数在stdlib.h头文件中
int *px = (int*)p;     //强制转换指针类型,使分配的内存可以按照int类型解析
ferr(p); //根据地址释放指针,此时p为迷途指针

p = NULL;

动态内存分配

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>

//void* calloc(size_t num.size_t size)
//分配内存函数,第一个参数为个数,第二个参数为内存大小,内存自动初始化为0
//void* realloc(void *ptr,size_t size)为以分配的内存重新分配空间并复制内容。
//参数一,已分配的内存地址,参数二重分配的字节数		如果能拓展就拓展,不能就重新分配

int main()
{
	int x;
	scanf("%d",&x);
	int *p = (int *)malloc( sizeof(int) * x );		//分配 x乘于int类型字节数的内存
	//分配失败则返回一个空指针NULL,返回值为空类型指针 malloc(1024) == NULL 判断是否分配成功
	//指针变量p指向分配的内存之后,不应更改指针的指向
	
	//实现动态数组,按照数组的方式访问,
	for (int *px = p,i = 0; px < p+x; i++,px++)		//指针法
	{
		*px = i;
		printf("%d\n",*px);
	}
	free(p);			//根据地址释放内存,一定要记得释放内存,除非空指针能反复释放
	p = NULL;			
	//内存释放之后,指针应该赋值为空,可以规避再次引用和反复释放的问题
									
	//for (int i = 0; i < x; i++)		//下标法
	//{
	//	p[i] = i;
	//	printf("%d\n",p[i]);
	//}

        system("pause");
}




静态内存分配由编译器完成,如为一个不大的数组分配内存

动态内存分配

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>

void detection(float* str)
{
	for (int i = 0; i < 5; i++)
	{
		if (str[i] < 60)
			printf("不及格成绩为%.2f 第%d个\n", str[i], i + 1);
	}

}

int mainaa()
{
	float* p = (float*)malloc(5 * sizeof(int));

	printf("输入五个成绩并以空格隔开\n");
	scanf("%f %f %f %f %f", p, p + 1, p + 2, p + 3, p + 4);
	detection(p);
	free(p);		//释放内存
	system("pause");
}





return 也有副本机制,存储在寄存器中,无法取地址  

一级指针作为函数返回值返回地址,一定不能返回指向栈的地址

#include<stdio.h>
#include <stdlib.h>

//void swap(int* pa, int* pb)			//无法交换pa pb的值
//{
//	int *p = pa;
//	pa = pb;
//	pb = pa;
//
//}

void swap(int* pa, int* pb)			//可以交换pa pb的值
{
	int *p = pa;
	*pa = *pb;
	*pb = *p;

}

int main()
{
	int a, b;
	int *pa = &a, *pb = &b;
	scanf_s("%d %d", pa, pb);
	printf("%d %d\n", a, b);
	swap(pa,pb);
	printf("%d %d\n", a, b);
	system("pause");
}




char *p = "你好,明天"; //指针存储常量字符串首地址,常量字符串不能修改


一级指针75% 二级指针20%,三级 四级指针.....N级指针 用于权限管理???
没有初始化的指针叫也指针
更高级指针可以改变低级指针的指向
   
指针声明一定要初始化


#作用:加上双引号
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章