有了指针,就有了自由访问内存空间的手段。
指针的基本概念:
每个变量都被存放在从某个内存地址开始的若干字节中。
指针也叫作指针变量,大小为4个字节(64位计算机为8个字节)的变量,其内容代表一个内存地址。
通过指针,能够对该指针指向的内存空间进行读写。
如果把内存的每一个字节都想象成一个房间,那么内存地址相当于房间号,而指针里存放的就是房间号。
指针变量的赋值、定义:
类型说明符 *变量名
int *p; p是一个指针,变量p的类型是int*。
char *c;c是一个指针,变量c的类型是char*。
float *d;d是一个指针,变量d的类型是float*。
如何访问int型变量a前面一个字节?
int a;
char*p=(char*)&a;
--p;
printf(“%c”,*p);//可能会导致运行出错
*p=‘A’;//可能会导致运行出错(可能不让访问)
(以上方法是错误的)
int *p1,*p2;int n=4;
char *pe1,*pe2;
p1=(int*)100;
p2=(int*)200;
cout<<"1)"< int *p=(int*)40000; *p=5000; int n=*p; 若干=sizeof(int),因为int*p。 T*p;T可以是任何类型,如float,int char。 p的类型是T*。 *p的类型是T。 通过表达式*p可以读写从地址p开始的sizeof(T)个字节。 *是间接引用运算符。 char ch=‘A’; char *pc=&ch; &取地址符 不需要通过变量就可以直接对内存空间进行操作。通过指针,程序能访问的内存空间就不仅限于变量所占有的内存空间。 不同类型的指针,如果不经过强制类型转换,不可以相互赋值。 int*pn,char*pc,char c=0x65; pn=pc;//类型不匹配,编译出错 pn=*c;//类型不匹配,编译出错 pn=(int*)&c; int n=*pn;//n值不确定 *pn=0x12345678;//编译没毛病,但运行会错误,可能会导致程序的崩溃 地址p1<地址p2 == p1 地址p1=地址p2 == p1==p2 值为真 地址p1>地址p2 == p1>p2 值为真 两个T*类型的指针p1和p2 p1-p2=(地址p1-地址p2)/sizeof(T) p:T*类型的指针 n:整数类型的变量或常量 p+n:T*类型的指针,指向地址:地址p+n*sizeof(T) n+p,p-n,*(p+n),*(p-n)含义自明 T*类型的指针p指向地址n p++,++p:p指向n+sizeof(T) p--,--p:p指向n-sizeof(T) #include using namespace std; void swap(int *p1,int *p2)//p1 形参 { int temp=*p1; *p1=*p2; *p2=temp; } int main(){ int n=3,m=4;//n实参 swap(&n,&m); cout< return 0; } 代码: #include using namespace std; int main(){ int a[200];int *p; p=a;//p指向数组a的初始地址,亦指p指向了a[0] *p=10;//使得a[0]=10 *(p+1)=20;//a[1]=20 p[0]=30;//p[i]和*p[i+1]是等效的,使得a[0]=30 p[4]=40;//a[4]=40 for(int i=0;i<10;i++)//对数组a的前十个元素进行赋值 *(p+i)=i; ++p;//p指向a[1] cout<
p=a+6;//p指向a[6] cout<<*p< return 0; } 翻转 代码: #include using namespace std; void reverse(int *p,int size){ for(int i=0;i int temp=p[i]; p[i]=p[size-i]; p[size-i]=temp; } } int main(){ int a[5]={1,2,3,4,5}; reverse(a,sizeof(a/sizeof(int)); for(int i=0;i<5;i++) cout<<*(a+i)<<','; return 0; } #include using namespace std; int n; int *a; int main(){ cin>>n; a=new int[n+1]; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=2;i<=n;i++) a[i]+=a[i-1]; for(int i=1;i<=n;i++) cout<
return 0; } 字符串常量的类型是char* 字符数组名的类型是char*,就是一个地址。 如: int i[10]; …… printf("%d\n",i); 代码: #include using namespace std; int main(){ char*p="please input your name:\n"; cout<
char name[20]; char*pname=name; cin>>pname; cout<<"your name is "< return 0; } 例题: 输入一个长度最大为100的字符串,以字符数组的方式存储,再将字符串倒序储存,输出倒序储存后的字符串(这里以字符指针为函数参数) #include using namespace std; void swapp(char &a,char &b){ char t; t=a; a=b; b=t; } void work(char *str){ int len=strlen(str); for(int i=0;i<=len/2;i++) swapp(str[i],str[len-i-1]); } int main(){ char s[110]; char *str=s; gets(s); work(str); printf("%s",s); return 0; } void*p; 可以用任何类型的指针对void指针进行赋值或初始化 double d=1.54; void*p=&d; void*p1; p1=&d; 因sizeof(void)没有定义,所以对于void*类型的指针p,*p无定义,++p,--p,p+=n,p-=n,p+n,p-n等均无定义。 头文件cstring中声明: void*memset(void*dest,int ch,int n); 将从dest开始的n个字节,都设置成ch,返回值是dest,ch只有最低的字节起作用。 头文件cstring中声明: void*memcpy(void*dest,void*src,int n); 将地址src开始的n个字节,拷贝到地址dest。返回值是dest。 注意!有缺陷,在dest区间和src区间有重叠时可能出问题! #include using namespace std; int a[111],n; int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; int *p=&a[1]; for(int i=1;i<=n;i++){ cout<<*p<<' '; p++; } return 0; } #include using namespace std; int a=10; double b=3.5; void *p; int main(){ p=&a;通过指针访问其指向的内存空间:
指针定义的总结:
指针用法:
指针的作用:
指针的互相赋值:
指针的运算:
1.两个同类型的指针变量可以比较大小(比较地址的大小)
2.两个同类型的指针变量,可以相减
3.指针变量加减一个整数的结果是一个指针
4.指针变量可以自增自减
5.指针可以用下标运算符“[ ]”进行运算
p是一个T*类型的指针,n是整数类型的常量或变量。
p【n】=*(p+n)
空指针:
地址0不能访问。指向地址0的指针就是空指针。
可以用“NULL”关键字对任何类型的指针进行赋值,NULL实际上就是整数0。
int *p1=NULL;char *pc=NULL;int *p2=0;
指针可以作为条件表达式使用,如果指针的值为NULL,则相当于假,反之为真。
if(p)等价于if(p!=NULL)。
指针作为函数参数:
指针和数组:
数组的名字是一个指针常量,指向数组的初始地址。
T a[n];
a的类型是T*
可以用a给T*类型的指针赋值
a是编译时其值就已经确定了的,不能够对a进行赋值
作为函数形参时,T*p和T p[ ]是等价的
void(int T*p){cout<
void(int T p[ ]){cout<
动态数组:
指针可以动态申请空间,如果一次申请多个变量空间,系统给的地址是连续的,就可以当做数组使用,这就是传说中的动态数组的一种。
动态数组的优点:
在OI中,对于大数据可能超空间的情况是比较纠结的事,用小数组只能得部分分,大数组可能爆空间同时又爆零,使用动态数组可以在确保小数据没问题的前提下,尽量满足大数据的需求。
指针和字符串:
注意:可以使用字符数组名或者字符指针输出一个字符串,而面对一个数值型数据是不能企图用数组名输出它的全部元素的。
字符串指针作函数参数:
将一个字符串从一个函数传递到另一个函数,可以用地址传递的方法,即用字符数组名作参数或用指向字符的指针变量做参数。在被调用的函数中可以改变字符串的内容,在主调函数中可以得到改变了的字符串。
字符串操作函数:
void指针:
内存操作库函数memset:
内存操作库函数memcpy:
试手:
1.输入n个数,使用指针变量访问输出。
2.无类型指针运用: