1,指针的定义
int main()
{
int * p; //p为变量的名字,int *表示变量p存放int类型变量的地址
int i = 5;
p = &i; //p保存i的地址,p指向i
*p=i;
printf("%d\n",*p);
return 0;
}
2,常见错误
#include<stdio.h>
int main()
{
int i = 5;
int * p;
int * q;
p = & i;
// (1) *q = p; //语法错误,*q为int类型,p为指针变量,类型不一致
// (2) *q = *p; //局部变量q未初始化,所谓初始化就是类似于p=&i
// (3) p = q; //q是垃圾值,q赋值给p,p也变成垃圾值
/* q的空间如果是属于本程序的,本程便可以读写q的内容
但是如果q内部是垃圾值,则本程序不能读写*q的内容
因为此时*q所代表的内存单元的控制权限并没有分配给本程序
运行(3)时,运行到*q就会报错 */
printf("%d\n",*q);
return 0;
}
3.经典例子----互换两个数字(采用调用函数的方法)
(1)错误例子
#include<stdio.h>
void swap(int a,int b)
{
int t;
t=a;
a=b;
b=t;
}
int main()
{
int a=3;
int b=8;
swap(a,b);
printf("%d %d\n",a,b);
return 0;
}
结果:
3 8
请按任意键继续. . .
分析:
因为向函数中传递的只是a和b的拷贝,在函数执行结束后其中的a和b的值会被释放,并不会影响调用者中a和b原有的值(即值传递的方法)。
(2)错误例子:
#include<stdio.h>
void swap(int * a,int * b)
{
int *t;
t=a;
a=b;
b=t;
}
int main()
{
int a=3;
int b=8;
swap(&a,&b);
printf("%d %d",a,b);
return 0;
}
结果:
3 8
请按任意键继续. . .
分析:
打算采用交换地址的方式来改变a,b的值,与(1)同理,拷贝后的&a,&b,在swap函数结束后被释放了
(3)正确例子-----改变指针的指向:
#include<stdio.h>
void swap(int * a,int * b)
{
int t;
t=*a;
*a=*b;
*b=t;
}
int main()
{
int a=3;
int b=8;
swap(&a,&b);
printf("%d %d\n",a,b);
return 0;
}
结果:
8 3
把主函数a,b的地址拷贝到swap函数中,在swap函数中通过指针a,b的指向对主函数的a,b进行修改,swap函数结束之后,a,b的地址也被释放
(4)正确例子—改变地址(实质也是改变指针的指向)
#include<stdio.h>
void swap(int ** a,int ** b) //int**表示存放了int*类型的地址,int**a=&p,int**b=&q
{
int *t;
t=*a; //*a=p,*b=q
*a=*b;
*b=t; //p,q互换,导致&a,&b地址互换
}
int main()
{
int a=10;
int b=55;
int * p;
int * q;
p=&a;
q=&b;
swap(&p,&q);
printf("a=%d,b=%d\n",*p,*q);
return 0;
}
结果:
a=55,b=10
请按任意键继续. . .
4.数组与指针的联系
1.数组名就是数组第一个元素的地址
#include<stdio.h>
int main()
{
int a[3]={1,2.3};
printf("%#x\n",&a[0]);
printf("%#x\n",a);
return 0;
}
结果:
0x3afd48
0x3afd48
请按任意键继续. . .
2.确定一个一维数组需要几个参数-------数组名,数组长度
调用函数输出一维数组的值
#include<stdio.h>
void f( int * pArr,int len)
{
int i;
for(i=0;i<len;i++)
{
printf("%d ",*(pArr+i)); //*(pArr+i)也可以写成 pArr[i]
}
printf("\n");
}
int main()
{
int a[5]={1,2,3,4,5};
int b[3]={77,88,99};
int c[100]={42,43,41};
f(a,5);
f(b,3);
f(c,100);
}
输出结果:
1 2 3 4 5
77 88 99
42 43 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
请按任意键继续. . .
#include<stdio.h>
void f(int * pArr,int len)
{
pArr[3]=100; //pArr[3]=*(pArr+3)
}
int main()
{
int a[5]={1,2,3,4,5};
printf("%d\n",a[3]);
f(a,5);
printf("%d\n",a[3]);
return 0;
}
结果:
4
100
请按任意键继续. . .
3.指向同一块存储空间的不同单元的指针变量只能相减
#include<stdio.h>
int main()
{
int i=5;
int j=99;
int *p=&i;
int *q=&j;
int a[5];
p=&a[1];
q=&a[4];
printf("%d\n",q-p); //p,q所指向的单元相差(q-p)个单元
return 0;
}
结果:
3
请按任意键继续. . .
5.动态存储空间
(1) sizeof( )函数
sizeof (数据类型)-----------------------------返回值就是该数据类型所占字节数
sizeof(变量名)----------------------------返回值是该变量所占字节数
#include<stdio.h>
int main()
{
int a=99;
char b='A';
double c=66.6;
int * p=&a;
char * q=&b;
double *r=&c;
printf("%d,%d,%d\n",sizeof(int),sizeof(char),sizeof(double));
printf("%d,%d,%d\n",sizeof(p),sizeof(q),sizeof(r));
}
结果:
4,1,8
4,4,4
请按任意键继续. . .
总结: 一个字节代表一个地址,一个字节8位
p,q,r所占字节数与操作系统(32位或是64位)以及编译器有关
其中,p,q,r只代表了变量所占的第一个字节
而 int(char,double)*则指出了占的字节长度
一个变量的地址用该变量的首字节来表示
(2)malloc函数-------动态内存分配
malloc是memory(内存) allocate(分配)的缩写
调用该函数需要头文件 #include<malloc.h>
#include<stdio.h>
#include<malloc.h>
int main()
{
int i=5;
int * p=(int *)malloc(4);
//请求系统为本函数分配4个字节,其中(int*)决定了变量的个数
*p=i;
printf("%d\n",*p);
free(p);
printf("%d\n",*p);
}
结果:
5
-572662307
请按任意键继续. . .
#include<stdio.h>
#include<malloc.h>
void f(int *p)
{
*p=200;
free(p);
}
int main()
{
int *p=(int *)malloc(4);
*p=10;
printf("%d\n",*p);
f(p);
printf("%d\n",*p);
}
结果:
10
-572662307
请按任意键继续. . .
(如果没有free(p)的话)结果:
10
200
(3)动态一维数组