目录
一、指针和指针变量
我们在定义一个变量 a 时,变量 a 本质上代表一个存储单元,CPU通过该存储单元的地址访问该存储单元中的数据。
所以a本来代表两个值:存储单元的地址和储单元中的数据。于是就有了二义性。
为了消除这种二义性,C语言规定a表示存储单元中的数据,&a表示存储单元的地址。
a存储单元中的数据可以是一个普通数值,也可以是另一个存储单元的地址,
比如:a = &b; 语句就是将b的存储单元的地址存入a存储单元中。
关于“指针”和“指针变量”比较严格的说法是这样的:
系统为每一个内存单元分配一个地址值,C/C++把这个地址值称为“指针”。如有int i=5;,存放变量i的内存单元的编号(地址)&i被称为指针。
“指针变量”则是存放前述“地址值”的变量,也可以表述为,“指针变量”是存放变量所占内存空间“首地址”的变量(因为一个变量通常要占用连续的多个字节空间)。比如在int i=5;后有一句int *p=&i;,就把i的指针&i赋给了int *型指针变量p,也就是说p中存入着&i。所以说指针变量是存放指针的变量。
(1) int* p=&a; //定义指针变量:此时为初始化指针变量,int* p定义了一个指向int类型指针p(我们使用星号把p声明为指针),并初始化p使其指向int类型的变量a,这里&num中的&是取地址操作符,当&作用于一个对象上时,它返回了该对象的地址。
(2) p //解引用 :在这里星号的作用是解引用(这里解引用的意思可能不太好理解,正确的说法应该是星号运算符给出指针变量p中存储的地址上存储的值(或者说是给出指针p指向的地址上存储的值))
由于在C语言中所有的变量都需要先定义声明后使用,要求p对应的存储单元中的数据一定是另一个存储单元的地址,于是,** a表示另一个存储单元中的数据。(这里* 操作符为解引用操作符,它返回指针p所指的对象(左值)。我们可以对*p赋值(对左值赋值),从而改变p所指的地址上所保存的值)
(3)int *p=&a; //定义整型指针变量§保存整型地址值
*p=100; //间接访问符(解引用)通过p间接访问变量a的值并把a的值赋为100
(4)int v2=0,*q=&v2; 等价于 int v2=0,*q; q=&v2;
p++和++p:
*p++是指针p所指的值然后指针加一;
*(p++)与上面一样;
(*p)++是指针p所指向的变量的值加一;
#include <iostream>
using namespace std;
void inc(int x) {
//传值调用,x只是形参,函数结束后即被销毁
x++;
cout << x << endl;
}
void dec(int& x) {
//传址调用,真正修改了指针所指向内容的值
x--;
cout << x << endl;
}
int main() {
int a = 1;
//int* p = a;//error:类型不匹配
int* q = &a;
int& p = a;
cout << q << endl;//q是指针变量,其值是a的地址
cout << *(&a) << endl;//*(&a)=a
cout << *q << endl;//a的值
cout << p << endl