#include <stdio.h>
int main(int argc, char *argv[])
{
/*
* 函数指针:专门用来存放函数地址的指针
* 函数地址:函数的入口地址,用函数名来代表
* 当一个函数指针指向了一个函数,便用该指针来调用该函数,将函数作为参数来传递给函数指针
* 函数指针 (低优先级-》高优先级),即从低优先级开始读
* 函数指针名称
* 函数指针变量:
<数据类型> (*<函数指针名称>)(<参数列表说明>);
【其()不能缺少,是表明指向函数的指针】
【也是区分函数指针和指针函数的关键 】
* 函数指针类型
typedef 函数指针变量
举例:
函数声明: int (*PF)(int,int); 或者 int (*PF)(int a,int b);
*PF:函数指针,可以用该指针调用一个函数
函数定义: ①PF = plus 指向一个函数,为下一步调用做准备
printf("%d\n",(*PF)(x,y));
int plus(int a,int b){ 返回计算过的值};
②printf("%d\n",test(15,5,plus)); 将函数作为参数来传递给函数指针
int test(int a,int b,int (*PF)(int,int)){返回函数指针变量的值}
===========================================================
*指针函数:
<数据类型> *<函数名称>(<参数说明>){语句序列;}
*函数名称:说明该函数返回一个地址量
举例:
char *mystrcpy(char *dest,const char *src){
char *p = dest;
while(*dest++ = *src++);
return p;
}
char *mystrcat(char *dest,const char *src){
char *p = dest;
while(*dest++);
dest--;
while(*dest++ = *src++);
return p;
}
*
*变量: <存储类型> <数据类型> <变量名>
*指针: <存储类型> <数据类型> *<指针变量名>
*一维数组:<存储类型><数据类型><数组名>[元素的个数];
*二维数组:<存储类型><数据类型><数组名>[行] [列];
* 数组指针:<存储类型> <数据类型> (*指针变量名)[数组元素个数]
*指针数组(行指针): <存储类型> <数据类型> *<指针变量名>[参数类型及个数]
也可以这样辨认:后结合性 先结合性 int *p[N];整形的指针数组,因为先结合数组,再结合指针
*/
/*===========================================*/
//数组指针:
// 数据类型:指向的数组里面元素的数据类型
// 指针的数据类型:指向数据的数据类型(数据==》数组)
// 数组的数据类型:数组里面元素的数据类型
int (*p)[10] = &a;//sz_pointer
//一个指向包含10个int元素的数组指针,注意:是一个指针
//这10个int元素被赋上a数组的地址,从入口地址开始
printf("变量、指针、指针函数、函数指针的格式及概念.\n");
return 0;
}
/*===========================================*/
//指针数组(行指针):
// int *p[10] 是一个数组,该数组存储存储着十个指针,
//比如:int *p[2] = {"hello","world"};
注意:该指针数组存储的是hello和world两个字符串的首地址,是首地址、是首地址、不是字符串!!!
//**数组是地址常量,指针是地址变量,数组名可以在运算中作为指针参与,但不允许被赋值.**//
0维 ===》 1维 ===》 2维
元素 元素的地址、一级指针 二级指针、一级指针的地址
元素 一维数组、一维数组名 二维数组名、行地址(行指针)
升维 -- &
降维 -- * [] [] 偏移并引用 *引用
int arr[3][4] = {0};
int (*p)[4] = arr;//int (*p)[4];
//p = arr;
arr[i][j] = p[i][j] = *(p[i] + j) = (*(p + i))[j] = *((*(p + i)) + j)
arr[0][0] -- 元素
p[0][0] --元素
*p + 1 -- &arr[0][1] // *p 代表p这个行指针数组的首地址,即&p[0][0]
arr[2] -- &arr[2][0]
*p[1] -- 元素arr[1][0] // *(p+1)
(*p + 1))[1] -- 元素a[0][2] //由于有[1],指偏移并引用,引用要降维,所以为元素
// *((*p+1)+1)
(p+1)[3] -- &a[4][0] // 虽然会越界,即无法访问,但是逻辑上是如此的
p+3 -- &arr[3]
arr[0]
*p☞该单元格
*p+1 *p+2 arr[1] arr[2]
例子1:
/*===============================================
* 文件名称:t3.c
* 创 建 者:
* 创建日期:2022年03月25日
* 描 述: 列指针遍历二维数组
================================================*/
#include <stdio.h>
int main(int argc, char *argv[])
{
int a[][3] = {3,2,1,5,4,6};
int i,j,r,c,n,*p;
p = &a[0][0];
r = sizeof(a)/sizeof(a[0]);
c = sizeof(a[0])/sizeof(int);
n = sizeof(a)/sizeof(int);
for(i=0;i<r;i++)
for(j=0;j<c;j++)
printf("%d %p\n",a[i][j],&a[i][j]);
printf("\n");
for(i=0;i<n;i++)
printf("%d %p\n",*(p+i),p+i);
return 0;
}
例子2:
/*===============================================
* 文件名称:t3_hang.c
* 创 建 者:
* 创建日期:2022年03月25日
* 描 述:行指针遍历数组
================================================*/
#include <stdio.h>
int main(int argc, char *argv[])
{
int a[][3]={1,2,3,4,5,6};
int i,j,r,c,(*p)[3];
p=a;
r = sizeof(a)/sizeof(a[0]);
c = sizeof(a[0])/sizeof(int);
for(i=0;i<r;i++){
for(j=0;j<c;j++){
printf(" a[i][j]=%d\n *((a+i)+j)=%d\n *(a[i]+j)%d\n",a[i][j],*(*(a+i)+j),*(a[i]+j));
printf(" a[i][j]=%d\n *(*(p+i)+j)=%d\n *(p[i]+j)=%d\n", a[i][j],*(*(p+i)+j),*(p[i]+j));
}
}
return 0;
}
例子3:
/*===============================================
* 文件名称:t4.1.c
* 创 建 者:
* 创建日期:2022年03月27日
* 描 述:理解指针数组名
* 功 能:用指针数组遍历二维数组所有元素
================================================*/
#include <stdio.h>
//指针数组的数组名,也代表着数组的起始位置。
/*
* 由于数组的元素已经是指针了,
则数组名就是数组首元素的地址,
因此数组名就是指针的地址,即多级指针。
*/
/* int* p[N];
p:&p[0];
p[0]:int*;
&p[0]:int**; */
// 用指针存储数组的起始位置为p或&p[0]
// 则 int **q=p;
// p=>&p[0]=>int **q
// p[0]=>int *q
int main(int argc, char *argv[])
{
int a[3][2]={1,2,3,4,5,6};
int* p[3],i,j;
int **q;
p[0]=a[0];
p[1]=a[1];
p[2]=a[2];
q=p;
for(i=0;i<3;i++){
for(j=0;j<2;j++){
printf("%d %d %d\n",*(p[i]+j),*(*(p+i)+j),p[i][j]);
printf("%d %d %d\n",*(q[i]+j),*(*(q+i)+j),q[i][j]);
printf("===========\n");
}
}
return 0;
}
例子4:
/*===============================================
* 文件名称:t4.c
* 创 建 者:
* 创建日期:2022年03月27日
* 描 述:指针数组的定义及初始化
================================================*/
#include <stdio.h>
int main(int argc, char *argv[])
{
int m=100,n=200;
int *p,*q;
p=&m;
q[0]=&m;
q[1]=&n;
printf("sizeof(p)=%ld\n",sizeof(p));
printf("&m=%p &n=%p\n",p,(p+1));
printf("&m=%p &n=%p\n",&m,&n);
printf("p[0]=%p p[1]=%p\n",p[0],p[1]);
printf("q=%p &q[0]=%p &q[1]=%p\n",q,&q[0],&q[1]);
return 0;
}
例子5:
/*===============================================
* 文件名称:t5.2.c
* 创 建 者:
* 创建日期:2022年03月27日
* 描 述:字符指针数组
================================================*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char s1[]="welcome";
char s2[]="to";
char s3[]="Liunx";
char* a1[3]={s1,s2,s3};
char* a2[3]={"welcome","to","Liunx"};
char** p;
p=a1;
printf("array1:%s %s %s\n",a1[0],a1[1],a1[2]);
for(int i=0;i<sizeof(a2)/sizeof(char*);i++)
printf("%s",*(p+i));
printf("\n");
p=a2;
printf("array2:%s %s %s\n",a2[0],a2[1],a2[2]);
for(int i=0;i<sizeof(a2)/sizeof(char*);i++)
puts(*(p+i));
puts("\n");
return 0;
}
例子6:
/*===============================================
* 文件名称:t5.c
* 创 建 者:
* 创建日期:2022年03月27日
* 描 述:字符指针,用字符数组存串
* 功 能:实现字符串的倒序
================================================*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char s[10];
char *p,*q,tmp;
printf("please input a string\n");
gets(s);
p=s;
q=s + strlen(s) - 1;
// q=s+s.length
//由于字符串是一样的,因此只需要比较其部分字符的长度
puts(q);
while(p<q){
tmp = *p;
*p = *q;
*q =tmp;
p++;
q--;
}
printf("%s\n",s);
return 0;
}
例子7:
/*===============================================
* 文件名称:t6_1.c
* 创 建 者:
* 创建日期:2022年03月27日
* 描 述:指针函数的定义和使用
* 指针函数:返回值是指针
================================================*/
#include <stdio.h>
#include <string.h>
char* mystring(void){
static char str[20]={0};
// 静态变量,当程序结束后才回收内存
// char str[20]={0};
// 没有 static 就相当于一个局部数组,放在堆栈中,函数执行完自动释放.
strcpy(str,"welcome");
return str;
}
char* mystring1(void){
char *str1="welcc";
// 字符串常量与静态变量类似
return str1;
}
int main(int argc, char *argv[])
// main(参数个数,指针->具体的参数)
{
puts(mystring());
puts(mystring1());
// char *str2="aa";
// 复制的字符串需要是一个变量,而不是字符串常量
char str2[10]="hsdhakba";
strcpy(str2,"welcome");
puts("\n");
puts(str2);
return 0;
}
例子8:
/*===============================================
* 文件名称:t6_2.c
* 创 建 者:
* 创建日期:2022年03月28日
* 描 述:指针函数mystring()返回一个堆空间上的地址str.
================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *mystring(void){
char *str = NULL;
str = (char*)malloc(20);
if(str==NULL){
puts("malloc error\n");
return str;
}
strcpy(str,"hello");
return str;
}
int main(int argc, char *argv[])
{
char* s;
if((s=mystring())!=NULL){
printf("%s\n",s);
free(s);
}
return 0;
}
例子9:
/*===============================================
* 文件名称:t6_function.pointer.c
* 创 建 者:
* 创建日期:2022年03月29日
* 描 述:声明一个函数指针变量,如何为函数指针赋值及如何通过函数指针来调用函数.
================================================*/
#include <stdio.h>
int test(int a,int b,int (*FP)(int,int));
int plus(int a,int b);
int minus(int a,int b);
int plus(int a,int b){
return (a+b);
}
int minus(int a,int b){
return (a-b);
}
int test(int a,int b,int (*FP)(int,int)){
return (*FP)(a,b);
}
int main(int argc, char *argv[])
{
int x=5,y=8;
int (*FP)(int,int);
FP=plus;
printf("%d\n",(*FP)(x,y));
FP=minus;
printf("%d\n",(*FP)(x,y));
printf("%d\n",test(15,5,plus));
printf("%d\n",test(15,5,minus));
return 0;
}
函数:
/*===============================================
* 文件名称:t6_function.c
* 创 建 者:
* 创建日期:2022年03月27日
* 描 述:函数、接口、封装、复用、模块化
================================================*/
#include <stdio.h>
void funs(){
printf("Please hammer Zhuoyang Shi fart!\n");
}
void fun(char* behavior,char* name){
behavior="Please hammer fart again!";
name="Zhuoyang Shi:";
printf("%s %s\n",name,behavior);
}
int main(int argc, char **argv)
{
char* be;
char* na;
funs();
fun(be, na);
return 0;
}
/*===============================================
* 文件名称:void_.c
* 创 建 者:
* 创建日期:2022年03月27日
* 描 述:
================================================*/
#include <stdio.h>
int main(int argc, char *argv[])
{
int m=100;
void* p;
p=(void*)&m;
// invalid use of void expression
// 无效使用void表达式.
// 这里可以不改,其对应着输出语句,printf()要改
printf("m:%d\n&m:%p\np:%p\n*p:%d\n",m,&m,p,*(int*)p);
// printf("m:%d\n&m:%p\np:%p\n*p:%d\n",m,&m,p,*p);
// dereferencing ‘void *’ pointer.
// 无效使用void表达式对“void *”指针进行引用.
return 0;
}