指针
如何得到指针?——取地址
&为取地址符,在
scanf("%d",&i)
中出现过,可以获得变量的地址,需注意它的操作数必须是变量。
不能对如(a+b)
来取地址,没有意义。
地址从数值上看是什么?
是无符号整型,且可以用%p来输出,自带标志十六进制的 0x。
int i;
printf("%p",&i);
数组的地址
#include<stdio.h>
int main(void)
{
int a[10];
printf("%p\n",&a);
printf("%p\n",a);
printf("%p\n",&a[0]);
printf("%p\n",&a[1]);
}
用以上代码在自己电脑上测试得到了
000000000061FDF0
000000000061FDF0
000000000061FDF0
000000000061FDF4
的结果。
说明数组名可以表示数组的第一个元素的地址。
而之后地址增加的步长又由数组元素的字长决定。
指针变量
得到指针变量
int i;
int *p=&i;
需要注意的是,int *p=&i;
中
int
不是p
的数据类型,而是p
指向的变量i
的数据类型。
且不同指针变量不允许赋值。
void*
可以表示不知道指向什么东西的指针。
指针变量与普通变量
指针变量的值是内存的地址
普通变量的值是实际的值
指针变量的值 是具有实际值的变量的地址 (好绕)
函数调用指针参数
void f(int *p);
int i=0;f(&i);
形式如上,得到地址后,可以用指针直接修改指向的变量。以下为示例
#include<stdio.h>
void f(int *p)
{
*p=0;
}
int main(void)
{
int i=1;//杂鱼函数,怎么可能碰的了我
printf("i是一个普通变量\n,i=%d,\n这是他经过函数后的变化\n",i);
f(&i);
printf("i=%d",i);//已经变成函数给定的形状了呢
}
所以我们其实可以利用指针来实现数字的交换。这就是
0地址
可以用0地址来表示特定情况。如返回指针无效。指针没被初始化。
而NULL可以帮助表示0地址。
指针与 const
const int *p=&i
;
会使*p
是const
。但不意味i不可修改。
int *const p=&i
;
会使p
是const
。
在函数调用的时候,为了保护原来的数组不动,可以设置参数为const
int sum(const int a[],int len);
指针的应用
在函数中
1.交换两个变量的值
2.帮助函数返回多个值
void swap(int *pa,int *pb)
{
int t=*pa;
*pa=*pb;
*pb=t;
}
帮助动态内存分配
使用malloc
函数前,需要#include <stdlib.h>
int *a=(int*)malloc(n*sizeof(int));//我需要存放n个int类型的数据
内存分配可以保证划定的区域不会再有别的数据写入到这里,但是也会有问题就是特别吃内存。
需要在合适时机使用free()
来释放内存。
指针与数组
之前的地址中已经认识到了一部分两者的关系
数组变量是特殊的指针。
函数调用数组实际是调用指针。
数组变量本身就表达地址。
[]
运算符可以对数组和指针做。
*
运算符可以取出指针指向的值和列表的第一个值。
数组变量是const的指针,不能被赋值。
指针运算
指针的+1
指针在+1的时候,不是实际数值在加一,而是加了那个指针所指类型的字长。
#include<stdio.h>
int main(void)
{
long long a[]={13,5,6,4,2,3,4};
long long *p=a;
printf("p=%p\n",p);
printf("p+1=%p\n",p+1);
}
运行后得到结果为
p=000000000061FDE0
p+1=000000000061FDE8
*p++
取出p所指的那个数据,并把p移到下一个位置。
说明*
的优先级没有++
高。
指针比较
<,>,<=,>=,==,!=都可以对指针做。