数组与指针(二)

指针
1.大小:32位编译器为4个字节,64位编译器为8个字节。
2.指针和指针变量:可以说变量i的指针是2000,而不能说i的指针变量是2000.
3.不能用一个整数给指针变量赋值。例:int *pointer=2000;编译系统不把2000认为是地址,而是一个整数。
4.& * 的运算级相同,自右向左结合。
5.区分:

 int *p1,*p2,*p,a,b;
 cin>>a>>b;
 p1=&a;
 p2=&b;
 if(a>b)
 {
   p=p1;p1=p2;p2=p;//a b的值不变,但p1指向b,p2指向a
 }
   
void swap(int *pointer1,int *pointer2);
int *p1,*p2,a,b,temp;
 cin>>a>>b;
 p1=&a;
 p2=&b;
 if(a>b)
 {
    swap(p1,p2);//a b的值改变,但p1仍指向a p2仍指向b
  }
 ...
 void swap(int *pointer1,int *pointer2)//区分swap(int a,int b)
 {
    int temp=*pointer1;
    *pointer1=*pointer2;
    *pointer2=temp;
  }

6.指向数组元素的指针

  • int a[10]; int *p; 则p=&a[0];与p=a;等价。a代表的是a数组的首元素的地址而不是整个数组
  • 若指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一元素,p+1意味着p的值(地址)增加d个字节(d为一个数组元素所占的字节数,与数组的类型有关,int型为4个字节)
  • 若p的值为&a[0],则p+i和a+i就是a[i]的地址,*(p+i) *(a+i)都表示a[i]。
  • 引用一个数组元素,可用:①下标法:如a[i]②指针法:如*(a+i)。
  • 用指针变量作函数形参接收数组地址,例:
void select_sort(int *p,int n);
int a[10];
.....
select_sort(a,10);//数组名代表的是数组首元素的地址,用数组名作函数的参数,传递的是数组元素的首地址
//c++编译系统将形参数组名一律作为指针变量来处理
//void select(int array[],int n);与void select(int *array,int n);等价
  • 实参数组名a代表一个固定地址,或者说是指针型常量,不可能改变a的值,如a++;就是错误的。而形参数组名是指针变量,并不是一个固定的地址,在函数执行期间,其可以被再次赋值。例:
function(array,n);//函数调用
{
  cout<<*array<<' ';//输出array[0]
  array+=3;
  cout<<*array<<'\n';//输出array[3]

7.字符串与指针

  • 用字符指针指向一个字符串
char *str="I love China!";
cout<<str<<endl;

对字符指针str的初始化,实际上是把字符串中第一个字符的地址赋给str.
上述代码等价于

char *str;
str="I love China!";
cout<<str<<endl;

8.函数与指针

  • 例:
int max(int x,int y);//函数声明
int *p(int ,int);//定义指向函数的指针变量p
int a,b,m;
cin>>a>>b;
p=max;//函数名代表函数的入口地址
m=p(a,b);

注意在定义指向函数的变量p时,(*p)两侧的括号不可省略,表示p先与 * 结合,它是指针变量
9.返回指针值的函数

  • 定义指针函数的一般形式: 类型名 *函数名(参数表列);如: int a(int x,int y);其中a是函数名。()优先级高于 * ,因此a先与()结合,为函数形式,函数前面有一个,表示此函数是指针型函数。,最前面的int表示返回的指针指向整型变量。
    10.指针数组和指向指针的指针
  • 指针数组的定义形式:例:int *p[4];区别:int (*p)[4];[]优先级比 * 高,后者是指向一维数组的指针变量
void sort(char *[],int n);
void print(char *[],int n);
char *name[]={"BASIC","FORTRAN","C++","Pascal"};//定义指针数组
int n=4;
sort(name,5);
print(name,5);

name[1]表示的是第一个字符串"FORTRAN"的起始地址。

指向指针的指针

  • 定义:例:char *(*p);等价于char **p;因为 * 自右向左结合,char p,则p表示的是指向字符的指针,则p表示的是指向字符指针的指针。
char **p;
char *name[]={"BASIC","C++","JAVA","FORTRAN"};
p=name+2;
cout<<*p<<'\n';//输出JAVA,可视为*p与name+2(name[2])等价
cout<<**p<<'\n';//输出J,*p与name等价,则**p等价于*(name+2)
  • 指向指针的指针也为二级间址,一个指针中存放一个变量的地址为单级间址。
    const指针
    一、指向常量的指针变量
  • 定义后,不允许通过指针变量改变它指向的对象的值。例:
int a=12,b=15;
const int *p=&a;
*p=15;//非法
p=&b;//p改为指向b,合法
a=15;//直接改变变量a的值,合法

指向常量的指针变量只是限制了通过指针变量改变它指向的对象的值。

  • 如果不想在调用函数时改变指针形参所指对象的值,可以将形参改为指向常量的指针变量,如:void fun(const int *p);
    二、常指针/常指针变量
  • 定义: 类型名 *const p2=&a;例:char *const p1=“China”;p1时字符指针变量,它的指向不能改变。
    三、指向常量的常指针
  • 定义:例:int a=10; const char *const p1=&a;
    void指针类型
  • void型的指针时过渡型的,它不指向确定的具有类型的数据,必须转换为指定一个确定的数据类型的数据,才能访问实际存在的数据,在实际使用时,要对它进行类型转换。例:
int a=3;
int *p1=&a;
char *p2="new";
void *p3;
p3=(void*)p1;//将p1的值转化为void类型,再赋给p3
cout<<p3<<endl;//非法,p3不能指向确定类型的量
cout<<*(int *)p3<<endl;//将p3的值转化为(int *)类型,然后赋给a
p2=(char *)p3;//将p3的值转化为char *类型,然后赋给p2
printf("%d",*p2);
  • 可以把非void型的指针赋给void型指针变量,但不能把void指针直接赋给非void型指针变量,必须进行强制转换。例:
p3=p1;//把非void型指针赋给void型指针变量,p3得到a的纯地址
p2=p3;//把void型指针变量直接赋给非void型指针变量,不合法
p2=(char *)p3;//先把p3强制转换为char *型,再赋给p2,合法
  • 指针变量可以有空值,即该指针变量不知想任何变量。eg. p=NULL;
  • 如果两个指针变量指向同一个数组额元素,则两个指针变量的差值值两个指针之间的元素个数。例: p1指向a[1],p2指向a[4],则p2-p1=(a+4)-(a+1)=3,但是p1+p2无实际意义。
  • 若两个指针指向同一个数组中的元素,则可以进行比较,指向前面的元素的指针变量小于指向后面的元素的指针变量。
  • 对指针变量的赋值应该注意类型问题,不是同一类型的不能直接赋值,必须进行强制转换。

12.引用

  • 对一个数据可以进行引用,它的作用是为一个变量起一个别名,&为引用声明符,并不代表地址。例:
int a;  
int &b=a;//声明b是a的“引用”
  • 引用不是一种独立的数据类型,对引用只有声明,没有定义。
  • 声明一个引用时,必须同时使之初始化,即声明它代表哪一个变量。
  • 在声明一个引用之后,不能再使之作为另一变量的引用。
  • 不能建立引用数组,例:
int a[5];
int &b[5]=a;
int &b=a[0];
  • 不能建立引用的引用,也没有引用的指针,如:
int a=3;
int &b=a;
int &c=b;//不合法
int *p=b;//不合法
  • 可以取引用的地址,如已声明b是a的引用,则&b就是变量a的地址&a
  • 区别引用声明符和地址运算符。
  • 引用其实就是一个指针常量,声明了b是a的引用时,实际上在内存上为b开辟了一个指针型的存储单元,在其中存放变量a的地址,输出引用b时,就输出b所指向的变量a值,相当于输出*b。
  • 举例:
void swap(int &,int &);
int i=3,j=5;
swap(i,j);
cout<<i<<' '<<j<<endl;//输出5 3
return 0;
....
void swap(int &a,int &b)//此处&a不是a的地址,而是指a是一个整型变量的引用,&是引用声明符,这就是地址传递方式
{
  int temp;
  temp=a;
  a=b;
  b=temp;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值