指针(c的关键)
内存是操作系统对物理存储器的抽象-虚拟存储器。
虚拟存储器可以看成是一个个连续的小方格,每个方格的大小是一个字节(byte) = 8 bit,可以存放一个八位的二进制数,每个小方格都会1有一个编号,2gb的虚拟存储器 大小就是21024^3 byte 编号的范围是0~1024^3 -1指针大概分析:指针是一个变量,他的值是可以变得,他里面存的是一个地址假设我们定义一个指针 int p; int a;如果p = &a;这个时候我们知道,a是一个变量,那么内存必定要给他分配一个地址来存储他,p指向a的意思就是p里面存的就是a的地址。所以p就是一个存着地址的变量。既然我们知道p里面存着a的地址,那么我们要找a就非常方便了,*p就表示p存的地址里面的值,也就是a的值。这句话怎么理解呢?
~.p存的是地址,比作你住的地方,那么p就表示你了,因为p就表示这个地址里面的数据。这个时候p和a是完全一样的了,假如你要改变a的值。a = a+1和p =p+1是完全一样的,都能达到对a进行操作的目的。但是p =p+1和p =(p+1)是不一样的,这个用的时候要特别注意,因为p里面是地址,那么(p+1)就表示这个地址加1后,地址加1那不就是换了一个地址吗?换了一个地址后里面存的就肯定不是a了,就像可能是你的邻居了。因为地址变了,所以就是p变了,因此*也变了,这个地方有点难理解,楼主多琢磨琢磨。总结一句话:指针是一个万能钥匙,可以指向任何一个地址,可以改变任何一个地址里面的数据(只读的除外),因此使用指针要注意安全,以免发生异常。
1、运算符&
scanf("%d",&i); //这里的&是一个运算符
·作用:取得变量的地址,它的操作数必须是变量。
· 在C语言中,sizeof() 是一个判断数据类型或者表达式长度的运算符
·int i;printf("%x",&i);
`int i;printf("%p",&i); // 地址输出用%p 地址的大小和int取决于编译器 引申: %X的意思是以十六进制数形式输出整数
1.%c:读入一个字符
2.%d:十进制整数
3.%f,%F,%e,%E,%g,%G 用来输入实数,可以用小数形式或指数形式输入
4.%o:八进制数
5.%s:读入一个字符串,遇空格、制表符或换行符结束。
6.%u:无符号十进制数
7.%%:输出百分号%
8.%i读入十进制,八进制,十六进制整数
9.%p读入一个指针
10.%n至此已读入值的等价字符数
11.%[]扫描字符集合
12.%a,%A读入一个浮点值(仅C99有效)
&不能对没有地址的东西取地址 先进后出,自顶向下 堆栈
a、指针就是一个保存地址的变量
int i;
int * p = &i; :表示p是指针,指向int,把i的地址交给p p表示i的值。 p里的值指向i那个变量的地址,此时说p指向了i。
int * p,q; int p,q; // p是一个int,q不是指针。 不管和int靠得近还是和p靠得近。int p,*q;此时p,q就都是指针了。
p是int型的数,p是*p的指针。
·p是一个指针变量的名字,表示此指针变量指向的内存地址,如果使用%p来输出的话,它将是一个16进制数
· *p表示此指针指向的内存地址中存放的内容,一般是一个和指针类型一致的变量或者常量
· &是取地址运算符,&p就是取指针p的地址
b、变量的值就是内存的地址。
·普通变量的值是实际的值。
·指针变量的值是具有实际值的变量的地址。
c、
void f(int *p) ; f需要int的指针 //在被调用的时候得到了某个变量的地址。
int i=0;f(&i) ; 当调用这个函数的时候应该交给它一个地址 用&取得变量的地址,然后将这个变量传给这个指针。 //在函数里可以通过这个指针访问外面的这个i。
#include <stdio.h>
void f(int *p);
void g(int k);
int main(void)
{
int i = 6;
printf("&i=%p\n", &i); //&i:地址值&i被传进了函数f中
f(&i);
g(&i);
return 0;
}
void f(int *p) //p:通过这个地址
{
printf(" p=%p\n", p);
printf("*p=%d\n", *p);
*p = 26; //*p:用*p这种方式访问到i变量
} //指针就是保存了内存的一个地址(门牌号),通过这个地址就能够访问对于内存中的数据
void g(int k)
{
printf("k=%d\n", k) //***p就是i=6的值,而p=&i,所以p和&i都是地址。 \*地址=值 注:\*p可以是和指针类型相同的变量也可以是常量**
} //p是i的地址,*p就是i(的值)。
d、
*是一个单目运算符,·在定义的时候只是说明是指针变量
·取用这个指针指向的地址所存储的变量
·用来访问指针地址的值,所表示的地址上的变量。
·可以是左值也可以是右值。
·int k=*p;
*p=k+1;
f、左值
赋值号左边不是变量,而是值,是表达式计算的结果。
a[0] =2; *p =3; 这两个左边的都不是变量。
g、反作用
&yptr -> (&yper) -> (yper的地址)-> yper 两者反作用,就是表示原来的那个变量 &yper -> &(*yper) -> &(y) ->得到y的地址 ->yper
h、传入地址
· i=6; int i;scanf("%d", i); 这样子输入编译是不会报错的,而运行则一定会出错,在32位中,整数和这个地址一样大 编译器误以为传入的是i的地址,实际上传进的是i的值6。
i、指针的实际应用
I、交换两个变量的值
#include <stdio.h>
void swap(int *pa, int *pb);
int main()
{
int a = 5;
int b = 6;
swap(&a,&b); //将a b的地址传递过awap函数中
printf("a=%d b=%d\n", a, b);
return 0;
}
void swap(int *pa, int *pb) //参数是两个指针,如果不用指针,那么从main函数传来的就是值,而不是变量。
{
int t=*pa; //*pa取出pa所代表的变量,赋值给t
*pa=*pb;
*pb= t;
}
b、指针应用二 ·函数返回运算的状态,结果通过指针返回