指针!!!!!!
指针指向的是地址,也称作指针变量,占有4个字节。可以对内存区域进行读写访问
指针的声明
int *p//定义一个指针变量p 类型是int* (还有char*等)
int *p=(int *) 40000//强制类型转换 p指向地址40000 *p表示从地址40000处开始的若干个字节内容。
*p=5000//往地址里写入5000
int n=*p//将地址40000起时的若干字节内容赋值给n
*p等价于存放在地址p处的一个某类型的变量。
&是取地址符
char ch1=‘A';
char *pc = &ch1;//使得pc指向变量ch1;
*pc =‘B’;//使得ch1=‘B’;
char ch2 = *pc//‘B’赋值给ch2;
pc = &ch2//pc指向ch2
*pc=‘D’//ch2=‘D';
有了指针就有了自由访问内存空间的手段。 程序访问内存不仅限于变量所占据的内存区域
例如 指针可以加减 ,使得它指向变量前面或者后面的内存区域。
指针容易发生数组越界之类的bug
指针的互相赋值必须强转。
int *pn,char *pc,char c = 0x65;
pn = pc//编译出错
pn = &c//出错
pn = (int *)&c;
int n=*pn//n值不确定。(字节数不同)
* pn=0x12345678//可能导致程序崩溃,因为超出了限定的字节,可能占用其他变量。
指针的运算
1.同类型的指针可以比较大小:等价于指向的变量比较大小。
2.同类型的指针变量可以相减:两个T*类型的指针 p1-p2=(地址1-地址2)/sizeof(T)
3.指针变量加减一个整数:p+n=地址p+n*sizeof(T);
4.自增自减 p++ ++p:p指向n+sizeof(T);反之则减。
5.[]:p[n]等价于 *(p+n);
如何访问int a前面的一个字节?
int a;
char *p = (char *)&a;//因为char类型占有的是一个字节,int型占了四个。
--p;
printf(“%c”,*p)//可能错误。 前面那个字节可能是操作系统不让访问的。
* p='A'//可能出错。
实例:
int main()
{
int *p1,*p2
char *pc1,*pc2;
p1=(int *)100;
p2=(int +)200;
cout<<p2-p1<<endl;//25
pc1=(char*)p1;
pc2=(char*)p2;
cout<<pc1-pc2;//-100
cout<<(p2+n)-p1<<endl;
int *p3=p2+n;
couit<<p3-p1<<endl;
cout<<(p2-10)+p1;
}
空指针:内容为零等指针或者指向地址0的指针。
NULL表示空指针 可以对任何类型的指针进行赋值。
int *pn=NULL;char*pc=NULL;INT *P2=0;
可作为条件表的是使用 if(p)等价于if(p!=NULL)
指针可做函数的参数使用
#include<iostream>
#include<cstdio>
using namespace std;
void swep(int* a,int* b)//交换数值
{
int t;
t=*a;
*a=*b;
*b=t;
}
int main()
{
int m=2,n=5;
swep(&m,&n);//使得a指向m,b指向n
cout<<m<<" "<<n;
}
指针和数组
数组的名字是一个指针常量,不能随便指了。
指向数组的起始地址。
T a[n] a的类型是T *
可以用a给一个T*类型的指针赋值使得被复制的指针指向a起始地址。
void(int *p){cout<<sizeof(p);}等价于 void func(int p[]) {cout<<sizeof(p);}
p[i] *(p+i)是等价的。
指针与数组的关系:
#include<iostream>
using namespace std;
int main()
{
int a[200];int * p;
p=a;
*p=10;
*(p+1)=20;
p[0]=30;
p[4]=40;
for(int i=0;i<=9;i++)
p[i]=i;
++p;
cout<<p[0]<<endl;
p=a+6;
cout<<*p<<endl;
}
数组颠倒:
#include<iostream>
using namespace std;
void Reverse(int * p,int size)
{
for(int i=0;i<=size/2;++i)
{
int tmp=p[i];
p[i]=p[size-1-i];
p[size-1-i]=tmp;
}
}
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)<<",";
}
指针和字符串
字符串常量和字符数组类型都是char*
#include <iostream>
using namespace std;
int main()
{
char*p="Please input your name:
";
cout<<p ;
char name[20];
char* pName=name;
cin>>pName;
cout<<"Your name is "<<pName;
}
字符串scanf读入的时候用%s,不用取地址符!!!
常用库函数
strchr:寻找字符c在字符串中第一次出现的位置。若找到就返回一个指向c位置的指针,若没有返回NULL
strstr:寻找主串中子串第一次出现的位置。返回值同上
stricmp:大小写无关的字符串比较,返回负数,0,或正数。
strncmp:比较s1,s2中前n个字符
strtok
atoi:把s内容转换为一个整形返回。如果是整数就返回本身、
atof:转成实数
itoa
void指针
可用任何类型的指针对void指针进行赋值
sizeof(void)没有定义 所以*p不知道到底是多大。
所以指针的一系列运算都没有定义!
内存操作
memset:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
int a[100];
memset(a,0,sizeof(a));
for(int i=0;i<=9;i++)
cout<<a[i];
}
又或者
char sz[200]=" ";
memset(sz,'a',10)//前10个变为a
memcpy(void *memcpy(void *dest,void src,int n)//将地址src开始的n个字节拷贝到地址dest,返回的是dest):
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
char a[100],b[100];
gets(a);
memcpy(b,a,2*sizeof(char));
//for(int i=0;i<=2;i++)
//cout<<b[i];
cout<<b;
}