打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
【原创】C++指针详解
指针

一,基础知识
1,内存(memory)
电脑是在CPU里面执行任务的,CPU就相当于人的大脑。CPU计算速度很快,所以我们写程序时,哪怕例如执行100多次循环,看起来似乎都是一秒就能执行好的。然而,CPU的存储能力很差,里面自带的几个寄存器(以32位为例)才只能存储区区32个字节。就算把段寄存器全部用上,也才只有44字节。所以CPU就需要一个东西辅助存储数据。这个存储数据的地方就是内存。
内存就像一个超大规模的住宅区,里面存储着CPU需要执行的数据。相对CPU来说,其实内存是一个外部寄存器。一般来说,程序都是保存在内存中执行的,CPU必须从内存读入执行数据。
2,内存地址
内存很大,为了识别每个内存,我们就需要给每个内存编一个号,这个号码就是内存地址。

二,指针
1,先来看一个例子:
#include<stdio.h>
int main(void) {
  int x=0;
  printf("%i",&x);
}
这个时候程序会输出一个奇怪的数字,不是0。这个数据在每次执行的时候会有一些变化,所以这里就不写出执行后输出的值了。
这里“&”是取地址操作符,表示取变量x的地址。这时候输出的就是x的地址。因为每次重新启动电脑的时候,操作系统都会根据当前内存中空余的地址,重新分配地址,所以每次执行时都会有一些小的变化。
2,什么是指针
先来看一个例子。
#include<stdio.h>
int main(void) {
  int a=10;
  int *p;
  p=&a;
  printf("%i",*p);
}
执行后会输出10。这里我们重点看第4行和第5行。
int *p表示声明指针变量p。p存放的就是一个内存地址,用“*”指针操作符就可以得到p存放的内存地址所指向的内容了。也就是说,p=&a表示把a的地址赋值给p,然后此时*p的值就是&a地址对应的值,就是a。
3,用指针取得最大值
现在有2个数,请用指针变量取得这2个数的最大值。
#include<stdio.h>
int main(void){
  int a,b,*p;
  scanf("%i%i",&a,&b);
  if(a>b)p=&a;//p指向a
  else p=&b;//p指向b
  printf("%i",*p);
}

三,指针的加减运算
1,数组
定义数组,我们一般用如下的语句:
int a[10];
这个时候操作系统就会给数组a分配10个连续的地址。注意是连续的。

2,指针的加减运算
#include<stdio.h>
int main(void) {
  int a[3]={1,2,3};
  int *p;
  p=&a[0];
  printf("%i", *(++p) );
} 
此时会输出2.我们看一下我们的内存:
设程序是从地址main开始运行的,那么内存如下
main1(a[0])
main+42(a[1])
main+83(a[2])
我们一开始把p指向a[0]所在的地址。++p,就是p的地址往前一个数,增加了sizeof(int),所以就是main+4,对应的数据就是2.
同理,p--就是往前一个地址,到达前面一个数据的空间。

四,指针和数组
1,
#include<stdio.h>
int main(void) {
  int a[5]={10,20,30,40,50};
  int *p;
  p=&a[0];
  printf("%i\n",*(p+2));
  printf("%i\n",a[2]);
}

输出结果应该是两个30.p的地址就是a[0]的地址,那么p+2就是a[2]的地址,所以*(p+2)就是a[2]。
同理我们知道,其实p就是a(数组名就是数组第一个元素的地址),所以,
*(p+i)=p[i]
其实根据加法交换率,*(p+i)=*(i+p)=i[p]。你可能不相信,把p[i]写成i[p]这样也没错。说白了数组其实就是指针。
为了写起来简便,我们一般把scanf中,&p[i]写作p+i。应该知道为什么吧。

2,(这个是新版本c++语言的写法,老版本c语言不支持)
#include<stdio.h>
int main(void){
  int n,*a,i;
  scanf("%i",&n);
  a=new int [n];
  for(i=0;i<n;i++){
    scanf("%i",a+i);
  }
  for(i=0;i<n;i++){
    printf("%i ",a[i]);
  }
}
首先输入一个数组元素个数,然后输入数组中的元素,最后输出数组。
这里a=new int [n]表示a向操作系统申请n个空间,这样a就可以当作数组使用了。否则a刚定义时,只有一个空间,不能往后继续存储(要不然就是数组越界),必须先向操作系统申请才能继续。
new是c++新引入的操作符:申请空间。这样做可以避免定义大数组时空间浪费。

顺便说一句,这是c++新引入的东西,老版本c语言是不支持的,所以编译的时候要注意。用c语言编译会出错。因为它不知道new是什么东西。
[Error] 'new' undeclared (first use in this function)

五,指针函数参数调用
现在要编写一个自定义函数swap(a,b),交换a,b变量的值。
错误示范1:
void swap(int a,int b){
  a=b;
  b=a;
  
}
错误:因为在a=b赋值完成后,a已经是b的值了,所以此时执行b=a,a已经不是原来的值了,错误。
错误示范2:
void swap(int a,int b){
  int tmp;
  tmp=a;//先把a保存起来
  a=b;
  b=tmp;
}
还是错误的。不信你运行一下试试,数值根本没变。
然而这么写却是对的。
int main(void){
  int a,b,tmp;
  scanf("%i%i",&a,&b);
  int tmp;
  tmp=a;//先把a保存起来
  a=b;
  b=tmp;
  printf("%i %i",a,b);
}
这是怎么会是呢?我们来了解一下函数的传值机制。
首先执行swap函数,参数把main里面的a和b传递给swap里面的a和b。方便描述,我们这里把main里面的用(main)表示,swap里面的用(swap)表示。
此时(swap)a=(main)a,(swap)b=(main)b。注意此时(swap)a和(main)a,(swap)b和(main)b地址不相等。
然后执行玩函数,(swap)a=(main)b,(swap)b=(main)a
然而(main)a,(main)b一点没变。
所以我们需要换一种传值方法。因为函数按值传递,所以我们传递函数的地址就可以了。
void swap(int *a,int *b){
  int tmp;
  tmp=*a;
  *a=*b;
  *b=tmp;
}
然后再写main。
错误示范3:
int main(void){
  int a,b,tmp;
  scanf("%i%i",&a,&b);
  swap(a,b);
  printf("%i %i",a,b);
}
首先下面出现了几行warning。
[Warning] passing argument 1 of 'swap' makes pointer from integer without a cast
[Warning] passing argument 2 of 'swap' makes pointer from integer without a cast
然后运行时成功崩溃了。
(弹出“xxx已停止工作,windows正在查找该问题的解决方案”)
这又是为什么呢?因为函数中,函数参数传送的是地址,a和b都是地址变量,函数中调用*a和*b才是值,所以参数中应该是地址才对。
基本正确的程序示例:
int main(void){
  int a,b,tmp;
  scanf("%i%i",&a,&b);
  swap(&a,&b);
  printf("%i %i",a,b);
}
运行成功。我们来总结一下:
1,遇到修改变量值的函数,调用时要注意用指针,要不然传送时只修改了自定义函数的值,没有修改main函数中的值。
2,调用时注意加上地址符号“&”。是不是觉得这样写很像我们用scanf的时候,
scanf("%i",&a)
其实scanf也运用了指针,后面需要写传送参数的地址。

六,结构体指针
1,结构体指针就是指向结构体的指针,其内存地址就是该结构体的第一个元素的地址。
如:

struct student a;
struct student *stu;
*stu=&a;

此段代码中stu指针变量指向的就是a。
2,引用
(*stu).name

表示*stu的name成员。注意括号虽然不好看,但是不能省略。
*stu.name相当于:*(stu.name)。

当然,还有一种更加方便的写法,就是用箭头记号,
stu->name。

也就是说,
(*a).b=a->b
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C语言【指针】一维数组与指针概念
第十章 指 针
C语言
C语言指针学习总结
指针作为函数参数,C语言指针作为函数参数详解
《C语言程序设计(第2版)》第08章指针
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服