指针知识点总结
'&':取地址运算符,求变量的地址
指针 :地址(内存最小地址单位为字节 所有变量用首地址标识) 地址值unsigned long数值
指针变量:存放地址数值的变量,在C语言种用'*'表示指针类型 指针变量通过间接引用(解引用)访问所指向的空间 '*'解引用运算符int a,value=555;
int *ptr; 或者 int *ptr=&value;
1.在声明或定义时'*'表示指针类型
2.除了声明或定义之外'*'表示解引用运算符
*ptr=4455;//相当于改变value为4455
a=*ptr;3.void *v;//无类型指针(万能型指针:可以存放任意类型变量的地址,但不可直接访问所指空间)
4.指针变量本身的空间大小与所指向的空间类型无关 与平台位数相关
指针变量可以执行以下算术运算:
1.同类型的指针可以比较== != > < >= <= (比较地址值的关系)2.指针可以加减某个整数,加减整数实现偏移 注意:仅在连续空间有意义
type *a;
a+n 向高地址偏移
a-n 向低地址偏移
偏移量:n*sizeof(type) 偏移N个所指向的空间大小3.同类型的指针可以减去同类型的指针
指针减指针得到 该空间内可以容得多少个所指向的类型数据
数组与指针
1.数组名单独作为右值或函数参数,它以首地址的形式存在,它是指向第一个元素
指针数组
int *ar[5];
char *names[10];
int **temp[5];
void (*funcs[10])(int,char);数组指针
int (*x)[6];函数指针:函数名单独作为右值或函数参数即为函数指针(通过函数指针可以直接调用函数)
void (*func)(char);
指针函数:返回值为指针的函数(函数的简称以返回类型为名)
指针的好处
- 指针节省数据空间,当存放数据过大时,使用指针,存放地址(避免爆栈)
- 在函数调用时,要求函数中实参改变,必须传其地址(数组除外),使用指针在函数中改变实参
指针的大小
指针的地址大小与数据类型无关,只与平台有关,(8B)64bit-------(4B)32bit
指针变量本身的空间大小与所指的空间类型无关
实参如果是数组名(ar),形参接到的为数组的 首地址 ,在其函数中 sizeof(ar)= 8(64bit);
指针的几种特殊用法
数组指针 int (*ar)[2] 是指针,指向该数组
指针数组 int *ar[2] 是数组,数组元素是指针
函数指针 int (*fun)(int a) 是指针,指向该函数
指针函数 int *fun(int a) 是函数,函数的返回值是指针地址
指针注意事项
万能型指针 void *v; 万能型指针 可以存放任意地址 但不可直接访问
int *ptr; 野指针 ptr值随机 指向随机的空间
*ptr=5566; //error!!!
int *ptr=NULL; 指向NULL 0地址(0地址为安全空间 访问则出错 避免修改随机空间)
取地址,交换实参的值
#include <stdio.h>
//*x-->a *y--->b
void swap(int *x,int *y)
{
int temp;
temp=*x;
*x=*y;
*y=temp;
}
int main(void)
{
int a=2,b=3;
printf("a:%d b:%d\n",a,b);
swap(&a,&b);
printf("a:%d b:%d\n",a,b);
return 0;
}
普通指针和数组指针的用法 、并求指针大小
#include <stdio.h>
int main(void)
{
int a=10,b=20;
int *ptr=&a;
printf("ptr:%p &a:%p *ptr:%d a:%d\n",ptr,&a,*ptr,a);
printf("size ptr:%d &ptr:%p\n",sizeof(ptr),&ptr);
int **qtr;
qtr=&ptr;
printf("qtr:%p &ptr:%p\n",qtr,&ptr);
printf("*qtr:%p ptr:%p\n",*qtr,ptr);
printf("**qtr:%p *ptr:%d a:%d\n",**qtr,*ptr,a);
/*
type tt;
type *yy
yy=&tt
*/
int ar[5]={1,2,3,4,5};
int (*xx)[5];//指向5个整型元素的数组的指针
xx=&ar;
int i;
for(i=0;i<5;i++)
{
//printf("%d ",ar[i]);
printf("%d ",(*xx)[i]);
}
putchar('\n');
return 0;
}
指针加减
指针可以加减某个整数,加减整数实现偏移
* type *ptr;
* ptr+n
* 偏移量:n*sizeof(type) 偏移N个所指向的空间大小同类型的指针可以相减:指针减指针得到 该空间内可以容得多少个所指向的类型数据
/*
* 2.指针可以加减某个整数,加减整数实现偏移
* type *ptr;
* ptr+n
* 偏移量:n*sizeof(type) 偏移N个所指向的空间大小
*/
#include <stdio.h>
int main(void)
{
int *i;
char *c;
short *s;
double *d;
void *v;
int **ii;
printf("i:%p i+1:%p\n",i,i+1);
printf("c:%p c+1:%p c-1:%p\n",c,c+1,c-1);
printf("s:%p s+1:%p\n",s,s+1);
printf("d:%p d+1:%p\n",d,d+1);
printf("v:%p v+1:%p\n",v,v+1);
printf("ii:%p ii+1:%p\n",ii,ii+1);
//注意:仅在连续空间有意义
int idx,ar[5]={11,22,33,44,55};
i=&ar[0];
c=&ar[0];
for(idx=0;idx<5;idx++)
{
//printf("%d ",ar[idx]);
//printf("%d ",*(ar+idx));
printf("%d ",*(i+idx));
//printf("%d ",i[idx]);
printf("%d",*(c+idx));
}
putchar('\n');
printf("------------------------------\n");
//指针比较
for(i=&ar[0];i<=&ar[4];i++)
{
printf("%d ",*i);
}
putchar('\n');
//同类型的指针可以相减:指针减指针得到 该空间内可以容得多少个所指向的类型数据
int count;
count=&ar[5]-&ar[0];
printf("count:%d\n",count);
count=(char *)200-(char *)100;
printf("count:%d\n",count);
count=(int *)200-(int *)100;
printf("count:%d\n",count);
count=(double *)200-(double *)100;
printf("count:%d\n",count);
return 0;
}
数组指针
数组名单独作为右值或函数参数,它以首地址的形式存在,它是指向第一个元素
//br=ar;//错误:将‘int *’赋值给‘int[5]’时类型不兼容
#include <stdio.h>
int main(void)
{
//数组名单独作为右值或函数参数,它以首地址的形式存在,它是指向第一个元素
//br=ar;//错误:将‘int *’赋值给‘int[5]’时类型不兼容
//
int ar[5]={11,22,33,44,55},br[5];
int *ptr;
ptr=ar;
int (*qtr)[5];
qtr=&ar;
char chs[5];
char *pp;
pp=chs;
int yy[3][2]={1,2,3,4,5,6};
int (*xx)[2];
xx=yy;
int (*zz)[3][2];
zz=&yy;
return 0;
}
整型指针数组 的典型例题和用法
int a=10,b=20,c=30,d=40,e=50;要求用一个函数内一个循环循环5次实现对a b c d e 分别累加1
// 1.int a=10,b=20,c=30,d=40,e=50;要求用一个函数内一个循环循环5次实现对a b c d e 分别累加1
#include <stdio.h>
int main(void)
{
int i,a=10,b=20,c=30,d=40,e=50;
//整型指针数组
int *ar[5]={&a,&b,&c,&d,&e};//int *
printf("a:%d b:%d c:%d d:%d e:%d\n",a,b,c,d,e);
for(i=0;i<5;i++)
{
*ar[i]=*ar[i]+1;
}
printf("a:%d b:%d c:%d d:%d e:%d\n",a,b,c,d,e);
return 0;
}
#include <stdio.h>
int main(void)
{
int a[2]={1,2},b[2]={3,4},c[2]={5,6};
int (*ar[3])[2]={&a,&b,&c};
int i;
//access array b
for(i=0;i<2;i++)
{
printf("%d ",(*ar[1])[i]);
}
putchar('\n');
return 0;
}
函数指针
- 函数名作为参数 或作为右值 也为其首地址 指向该函数
- 通过函数指针可以直接调用函数
//反汇编 objdump -S a.out > tt.s
#include <stdio.h>
//typedef将一种已经存在的类型 取个别名
typedef unsigned int u32;
typedef int array_t[3][2];
typedef void func_t(char *);
void sayHello(char *name);
//void func(void (*f)(char *),int num)
void func(func_t *f,int num)
{
f("func");
}
int main(void)
{
int a[3][2];//array_t a;
printf("size of a:%d\n",sizeof(a));
array_t *x; //int (*x)[3][2];
x=&a;
sayHello("king");
//函数名作为参数 或作为右值 也为其首地址 指向该函数
//通过函数指针可以直接调用函数
printf("main:%p sayHello:%p\n",main,sayHello);
func_t *ptr;//void (*ptr)(char *);
ptr=sayHello;
//(*ptr)("tom");
ptr("marray");//直接调用
int value=111222;
//函数作为另一个函数的参数
func(sayHello,value);
return 0;
}
void sayHello(char *name)
{
printf("hello %s\n",name);
}
函数指针的高级用法
- 用一个循环分别求ab之间的 + - * / %运算
//用一个循环分别求ab之间的 + - * / %运算
#include <stdio.h>
typedef int func_t(int,int);
#if 0
int add(int a,int b);
int sub(int a,int b);
int sum(int a,int b);
int mydiv(int a,int b);
int mod(int a,int b);
#else
func_t add,sub,sum,mydiv,mod;
#endif //
int main(void)
{
int i,a=10,b=5,value;
//int (*ar[5])(int,int)={add,sub,sum,mydiv,mod};
//ar为返回值为int 且有两个int参数的函数指针数组
func_t *ar[5]={add,sub,sum,mydiv,mod};
char ops[5]={'+','-','*','/','%'};
for(i=0;i<5;i++)
{
value=ar[i](a,b);
printf("%d%c%d=%d\n",a,ops[i],b,value);
}
return 0;
}
int add(int a,int b){return a+b;}
int sub(int a,int b){return a-b;}
int sum(int a,int b){return a*b;}
int mydiv(int a,int b){return a/b;}
int mod(int a,int b){return a%b;}