资源描述
# include <stdio.h>
Void g(int*p,int*q)
{
*p=1;
*q=2;
}
Int main(void)
{
Int a=3,b=5;
g(&a,&b);
Printf(“%d%d\n”,a,b);
Return 0;
}
指针使函数返回一个以上的值
Int f(int i,int j)
{
return 100;
// return 88;error
}
Int main (void)
{
Int a=3,b=5;
a=f(a,b);
b=f(a,b);
}
只能返回一个值
指针
★指针的重要性
表达一些复杂的数据结构
快速传递数据
使函数返回一个以上的值
能直接访问硬件
能方便解决字符串
是理解面向对象语言中引用的基础
总结:指针是C语言的灵魂
★指针的定义
☆地址
内存单元的编号
从零开始的非负整数
范围:4G
☆指针
1.指针就是地址,地址就是指针
2.指针变量是存放地址的变量
3.指针和指针变量是两个不同的概念
4.叙述时通常把指针变量简称为指针,实际它们含义不同样
5.指针的本质就是一个操作受限的非负整数
★指针的分类
☆基本类型指针(重要)
#include<stdio.h>
int main(void)
{
int *p; //p是变量的名字,int*表达p变量存放的是int类型变量的地址
Int*p;不表达定义了一个名字叫做*p的变量
Int*p;应当理解为:p是变量名,p变量的数据类型是int*类型
所谓int*类型,实际就是存放int变量地址的类型
int i=3;
char ch=’A’
p=&i; //OK
1.p保存了i的地址,因此p指向i
2.p不是i,i也不是p,修改p的值不影响i的值,修改i的值也不影响p的值
3.假如一个指针变量指向了某个普通变量,则*指针变量 完全等同于 普通变量
例:若p指向i,则*p=i (*p和i 可互相替换)
p=&ch;//error
//p=i; //error,由于类型不一致,p只能存放int类型变量的地址,不能存放int类型变量
//P=55;//error,因素同上
return 0;
}
△附注:
▷*的含义:
1.乘法
2.定义指针变量
Int*p; //定义了一个名字叫做p的变量,int*表达p只能存放int变量的地址
3.指针运算符
该运算符放在已经定义好的指针变量的前面
假如p是一个已经定义好的指针变量
则*p表达以p的内容为地址的变量
▷如何通过被调函数修改主调函数普通变量的值
1.实参必须为该普通变量的地址 &...
2.形参必须为指针变量 *...
3.在被调函数中通过 *形参名=...... 的方式就可以修改主调函数相关变量的值
例子: 经典指针程序:互换数值
#include<stdio.h>
void huhuan3(int *p, int*q)
//形参的名字是p和q,接受实参数据的是p和q,而不是*p和*q
{
int t;//假如要互换*p和*q的值,
则t必须是int,不能是int*
t=*p;//p是int*,*p是int
*p=*q;
*q=t;
return;
}
int main(void)
{
int a=3;
int b=5;
huhuan3(&a,&b);
/*huhuan3(*p,*q)是错误的
huhuan3(a,b)也是错误的*/
printf(“a=%d,b=%d/n”,a,b);
return 0;
}
a=5,b=3
Press any key to continue
互换成功
#include<stdio.h>
void huhuan(int a, int b)
{
int t;
t=a;
a=b;
b=t;
return;
}
int main(void)
{
int a=3;
int b=5;
huhuan(a,b);
printf(“a=%d,b=%d/n”,a,b);
return 0;
}
a=3,b=5
Press any key to continue
互换失败
#include<stdio.h>
void huhuan2(int *p, int *q)
{
int *t;//假如要互换p和q的值,
则t必须是int*,不能是int
t=p;
p=q;
q=t;
return;
}
int main(void)
{
int a=3;
int b=5;
huhuan2(&a,&b);
/*huhuan2(*p,*q);是错误的
huhuan2(a,b);也是错误的*/
printf(“a=%d,b=%d\n”,a,b);
return 0;
}
a=3,b=5
Press any key to continue
互换失败
形参和实参是不同的变量,修改形参不会改变实参
▷指针常见错误
#include<stdio.h>
Int main(void)
{
Int i=5;
Int*p;
Int*q;
P=&i;
//*q=p;//error语法编译会犯错
//*q=*p;//error
P=q;//q是垃圾值,q赋给p,p也是垃圾值
printf(“%d\n”,*q); //13行
/*q的空间是属于本程序的,所以本程序可以读写q的内容,
但是假如q内部是垃圾值,则本程序不能读写*q的内容
由于此时*q所代表的内存单元的控制限权并没有分派给本程序
所以本程序运营到13行时就会立即犯错*/
return 0;
}
☆指针和数组
△指针和一维数组
▷一维数组名
一维数组名是个指针常量
它存放的是一维数组第一个元素的地址
▷下标和指针的关系
假如p是个指针变量,则p[i]永远等价于*(p+i)
▷拟定一个一维数组需要几个参数
(假如一个函数要解决一个一维数组,则需要接受该数组的哪些信息)
需要两个参数:
数组第一个元素的地址
数组的长度
1 2 3 4 5
-1 -2 -3 4 5 -6
1 99 22 33 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
Press any key to continue
int main(void)
{
int a[5]={1,2,3,4,5};
int b[6]={-1,-2,-3,4,5,-6};
int c[100]={1,99,22,33};
f(a,5);//a是int*
f(b,6);
f(c,100);
return 0;
}
# include<stdio.h>
//f函数可以输出任何一个一维数组的内容
void f(int * pArr, int len)
{
int i;
for(i=0,i<len,++i)
printf( “%d”,*(pArr+i) )
//*(pArr+i)等价于pArr[i] b[i] *(b+i)
printf(“\n”);
}
#include<stdio.h>
Void f(int*pArr,int len)
{ pArr[2]=10;
//pArr[2]==*( pArr+2)==*(a+2)==a[2]
}
Int main(void)
{
int a[6]={1,2,3,4,5,6}
printf(“%d\n”,a[2]);
f(a,5);
printf(“%d\n”,a[2]);
//a=&a[2];//error 由于a是常量
//printf(“%#X,%#X\n”,a,&a[0]);
//a==&a[0]
Return 0;
}
3
10
Press any key to continue
# include<stdio.h>
void f(int * pArr,int len)
{ pArr[3]=88; //10行
}
int main(void)
{
int a[6]={1,2,3,4,5,6}
printf(“%d\n”,a[3]); //17行
f(a,6);
printf(“%d\n”,a[3]);
//19行 若写为&a[3]则输出结果为a[3]的地址
return 0;
}
/*在VC++6.0中输出结果是
4
88*/
一定要明白10行的pArr[3]和
17行 19行的a[3]是同一个变量
# include<stdio.h>
Void OutArr(int*pArr,int len)
{
Int i;
For(i=0;i<len;++i)
Printf(“%d\n”,pArr[i]);
}
Int main(void)
{
Itn a[5]={1.2.3.4.5};
OutArr(a,5);
Return 0;
}
1
2
3
4
5
Press any key to continue
▷指针变量的运算
指针变量不能相加,不能相乘,不能相除
可以相减(仅当两个指针变量指向的是同一块连续空间中的不同存储空间)
#include<stdio.h>
Int main(void)
{ int i=5;
Int j=10;
Int*p=&i;
Int*q=&j;
Int a[5];
p=&a[1];
q=&a[4];
Printf(“p和q所指向的单元相隔%d个单元\n”,q-p);
}
p和q所指向的单元相隔3个单元
Press any key to continue
#include<stdio.h>
Int main(void)
{ int i=5;
Int j=10;
Int*p=&i;
Int*q=&j;
//p-q没有实际意义
Return 0;
}
▷一个指针变量到底占几个字节
预备知识:
sizeof(数据类型)
功能:返回值就是该数据类型所占的字节数
例子:sizeof(int)=4 sizeof(char)=1 sizeof(double)=8
sizeof(变量名)
功能:返回值是该变量所占的字节数
假设p指向char类型变量(1个字节)
假设q指向int类型变量(4个字节)
假设 r指向double类型变量(8个字节)
4 4 4
Press any key to continue
#include<stdio.h>
Int main(void)
{ char ch=’A’;
Int i=99;
Double x=66.6
Char * p=&ch;
Int *q=&i;
Double * r=&x;
Printf(“%d%d%d\n”,sizeof(p),sizeof(q),sizeof(r))
Return 0;
}
△指针和二维数组
☆指针和函数
☆指针和结构体
☆多级指针
专题:
动态内存分派(重难点)
传统数组的缺陷:
1.数组长度必须事先制定,且只能是常整数,不能是变量。
例子:int a[5]; //OK
Int len=5; int a[len];//error
Int a[5.6];//error
2.传统形式定义的数组,该数组的内存程序员无法手动释放
为什么需要动态分布内存
动态内存分派举例-动态数组的构造
静态内存和动态内存的比较
跨函数使用内存的问题
展开阅读全文