前言
一、取址运算符 &
sizeof运算符
- 是一个运算符,给出某个类型或者变量在内存中所占的字节数。
sizeof(int);
sizeof(i);
& 运算符
- 获得变量的地址, 它的操作数必须是变量
获取地址的示例:(地址用16进制表示合适)
#include<stdio.h>
int main()
{
int i = 0;
printf("0x%x",&i);
return 0;
}
也可以用 %p 来输出地址
printf("0x%p",&i);
- & 不能对没有地址的东西取地址
- &右边必须有明确的变量
变量在内存上分配在堆栈的地方,自顶向下。
数组的地址
int main()
{
int a[10];
printf("%p\n",&a);
printf("%p\n",a);//直接通过 a 来输出地址也可以
printf("%p\n",&a[0]);
printf("%p\n",&a[1]);
return 0;
}
输出:
000000000062FDF0
000000000062FDF0
000000000062FDF0
000000000062FDF4
观察以上结果可以发现,对于数组 a 而言,a 和 a[0] 的地址是相同的,与 a[1] 之间差了 4 个字节。
二、指针
保存地址的变量。
示例:
1.
int i;
int* p = &i;
*表示p是一个指针,指向一个int类型的变量。
int* p,q;
int *p,q;
无论* 离 int 远或者近,都表示 p是指向int 的指针,而 q 是变量。
- 普通变量的值是实际的值
- 指针变量的值是具有实际值的变量的地址
指针作为函数的参数
- 声名
void f(int *p);
- 函数 f 在被调用的时候,得到变量的地址
int i = 0;
f(&i);
- 在函数里可以通过指针,访问外面的变量 i
否则,函数 f(i) 得到的只是变量 i 的值,但是和外面的变量 i 无关。
访问地址上的变量 *
- *是一个单目运算符,用来访问指针的值所表示的地址上的变量
- 可以做右值,也可以做左值
int k = *p;//读取
*p = k + 1;//写入
一个完整的代码
#include<stdio.h>
void f(int *p);
int main()
{
int i = 6;
printf("&i = %p\n",&i);
f(&i);
return 0;
}
void f(int *p){
printf("p = %p\n",p);
printf("*p = %d\n",*p);
}
这里,当 p 是一个指针变量时, *p 可以看作一个整体,表示的是 int 类型的变量。通过 *p访问到了 Int i 里的值。
如果改变 *p 的值。因为 *p是 变量 i中的值,所以变量i 也会相应改变。
*p = 26;
#include<stdio.h>
void f(int *p);
void g(int k);
int main()
{
int i = 6;
printf("&i = %p\n",&i);
f(&i);
g(i);
return 0;
}
void f(int *p){
printf("p = %p\n",p);
printf("*p = %d\n",*p);
*p = 26;
}
void g(int k){
printf("k = %d\n",k);
}
输出:
&i = 000000000062FE1C
p = 000000000062FE1C
*p = 6
k = 26
--------------------------------
Process exited after 0.14 seconds with return value 0
请按任意键继续. . .
可以看到,i的值确实被改变了。
C语言的函数是值得传递,因此,函数中的参数变化,对调用的变量不产生影响。但是通过指针变量,就可以访问到函数外的变量,并且改变它的值。
三、指针与数组
数组传入函数
将一个变量传入函数,参数接收到的是对应的值。将数组传入函数时,接收到什么。
数组变量是特殊的指针
- 数组变量本身表达地址
所以,
int a[10];
int *p = a; // 无需使用 & 取址符
- 但是数组的单元表达的是变量,需要用 & 取址符。
a == &a[0]//数组的单元使用取址符
- [ ] 运算符可以对数组做,也可以对指针做:
p[0] <==> a[0]
p[0]的意思:如果,我以为我所指的p是个数组的话,他所指出的第一个单元。
- * 运算符可以对指针做,也可以对数组做
- 数组变量是const的指针,所以不能被赋值
所以两个数组之间不能之间赋值。