指针(一)
在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
——百度百科
运算符&取得变量的地址
·获得变量的地址,他的操作数必须是变量;
·int i ;printf("%x",&i);
int main(void){int i = 0;printf("0x%x\n", &i);return 0;}
运行结果,需要注意的是,取地址变量在每台PC和每个编译器的结果都是不一样的,我们不必太过关注每次结果不同
0x62feac
老师视频这里解释他编译器这里有报错,上面的%x需要替换成%p,我用的Dev C++没有报错,这里不再继续探究,该地方跳过,如果报错,记的选择32位编译
#include <stdio.h> int main(void){int i = 0;int p;p = &i; //报错,需要(int)&强制转换//p = (int)&i; //报错后,将&i 强制转换为int类型即可printf("0x%x\n", &i);printf("%p\n", &i); return 0;}
强制转换后的运行结果,注意的是,这里取出来的和老师取的值是不同的,不影响课程
0x62fea8
0062FEA8
上面在编译器里用32位架构编译的结果,老师换成64位再编译,会报错,
“cast from ‘int*’ to ‘int’ loses precision ”
64位系统上指针类型占用8个字节,而int类型占用4个字节,所以会出现loses precision。
从这里可以看出&可以给我们取出一个变量的地址,从而可以得出,我们需要printf输出一个地址时,需要的是%p,地址和整数是不同的
· 地址的大小是否与int相同取决于编译器
&不能取的地址
· &不能对没有地址的东西去地址 · 如&(a+b) · 如&(a++) · 如&(++a)
下面来看一段上面例子的代码
#include <stdio.h> int main(void){int i = 0;int p;p = (int)&i; //p = (int)&(i+p); //p = (int)&(i++); //p = (int)&(++i); printf("0x%x\n", &p);printf("%p\n", &i); return 0;}
把上面三个注释分别去掉,得出的报错信息,三个报错类型基本一致的,都是提示不能取这样的值
D:\C\指针.cpp:8:16: error: lvalue required as unary ‘&’ operand p =
(int)&(i+p);
其他类型的&
· 变量的地址 · 相邻的变量的地址 · &的结果的sizeof · 数组的地址 · 数组单元的地址 · 相邻的数组单元的地址
// 变量的地址#include <stdio.h> int main(void){int i = 0;int p;printf("%p\n",&i); // 变量的地址printf("%p\n", &p); // 相邻变量的地址printf("%p\n",sizeof(int)); // sizeof(int)地址return 0;}
执行结果
0061FEAC
0061FEA8
00000004
C在16进制代表的是12,从这里可以看出AC和A8中间差了4位,从上面得知int占据的是4个字节,因此他们是相邻的内存地址,在堆栈里自顶向下分配的,他们的差距是4,刚好等于sizeof(int)
// 数组的地址#include <stdio.h> int main(void){int a[10];printf("&a=%p\n",&a); // a交给取地址符 printf("a=%p\n", a); // a直接当一个地址 printf("a[0]=%p\n",&a[0]); // 获取a[0]的地址 printf("a[1]=%p\n",&a[1]); // 获取a[1]的地址return 0;}
执行结果,从这里可以看出相邻单元的数组差距,永远是4
&a =0061FE88
a =0061FE88
a[0] =0061FE88
a[1] =0061FE8C