黑马程序员_C语言基础_指针
来源:互联网 发布:ubuntu安装fcitx五笔 编辑:程序博客网 时间:2024/04/30 20:12
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1、指针变量
指针是一个常量,简单来说就是内存单元的地址;指针变量就是一个变量,记录存放地址的一个变量。
形式:类型说明符 *变量名
A注意问题:
- *表示定义的是指针变量
- 指针变量只能存放地址,不能是数值和字符
- 指针变量和其他普通变量一样,也有全局变量和局部变量
B*的用法:
- 定义一个指针变量
- 获取指针变量所对应的存储单元的内容值
C初始化和引用
- 完全初始化:int *p=&a;即p指向了a;int *p=&a,*p1=&a;即p,p1都指向了a
- 部分初始化:int *p=&a,*p1;
- 引用:int a,*p; //定义了整型变量 a 和 指向整型变量的指针变量 p。
p=&a;//“&”为取地址运算符,将a的地址赋给指针变量 p
*p=a;//* p 为指针变量 p 所指向的存储单元的内容,即 p 所指向的变量的值
D调用函数
指针变量可以作为函数参数,它可以将一个变量的地址传送到另一个函数中,在调用过程中会临时分配存储空间,调用完之后内存空间也会随之释放。
调用过程中实参变量和形参变量之间的数据传递是单向的“值传递”方式,指针变量作函数参数在传递也是单向的值传递,不可能通过调用函数来改变实参指针变量的值,但可以改变实参指针变量所指向变量的值。要想实现通过调用函数改变实参的值,可以通过调用实参的地址,通过改变形参指向实参的地址来达到改变实参的值。
下面三种情况都是调用函数,传递的形参分别为值,地址的情况,对实参的影响。
1)、
void swap2(int a,int b){//定义中间变量int temp;//进行值的交换temp = a;a = b;b = temp;}int main(int argc, const char *argv[]){//定义两个变量并赋值int a = 3, b = 4;printf("交换之前的值:a=%d,b=%d\n", a, b);//调用函数swap2(a, b);printf("交换之后的值:a=%d,b=%d\n", a, b);return 0;}
结果:
分析:在主函数进行swap2(a, b);时,开始调用子函数,这时候为子函数分配了一个存储空间,并有变量a,b,进行交换,虽然此时执行完语句进行a,b的调换,但是子函数掉用完释放空间,形参并没有传递给实参,实参还是原来的值。
2)、
void swap2(int *a,int *b){//定义中间变量int *temp;//进行值的交换temp = a;a = b;b = temp;}int main(int argc, const char *argv[]){//定义两个变量并赋值int a = 3, b = 4;printf("交换之前的值:a=%d,b=%d\n", a, b);//调用函数swap2(&a, &b);printf("交换之后的值:a=%d,b=%d\n", a, b);return 0;}
结果:
分析:在主函数进行swap2(&a, &b);时,开始调用子函数,这时候为子函数分配了一个存储空间,传递的是a,b的地址,这个时候定义了临时中介的地址,此时执行语句进行交换的是a,b的地址,并没有改变a,b的值,但是子函数掉用完释放空间,实参还是原来的值。
3)、满意结果值交换
void swap2(int *a,int *b){//定义中间变量int temp;//进行值的交换temp = *a;*a = *b;*b = temp;}int main(int argc, const char *argv[]){//定义两个变量并赋值int a = 3, b = 4;printf("交换之前的值:a=%d,b=%d\n", a, b);//调用函数swap2(&a, &b);printf("交换之后的值:a=%d,b=%d\n", a, b);return 0;}
结果:
分析:在主函数进行swap2(&a, &b);时,开始调用子函数,这时候为子函数分配了一个存储空间,传递的是a,b的地址,根据形参*a指向实参a地址,这个时候定义了临时中介的值,通过执行下面的语句*a,*b进行改变交换的是实参a,b的值,子函数掉用完释放空间,实参值已经被交换。
2、二级指针
简单而言就是指向指针的指针。
用图的形式表示如下:
例子:
int a=5;//定义一个整型变量为5
int *p=&a;//定义一个指针变量指向变量a地址,则可以描述为p=&a,*p=a=5
int **p1=&p;//定义一个二级指针变量指向变量p地址,则可以描述为p1=&p,*p1=p=&a,**p1=*p=a=5
3、数组指针
A定义:数组元素的指针就是数组元素的地址。
一般形式为:int a[10];int *p;p=a=&a[0]=首元素的地址。
B初始化
若指针变量 p 已指向数组元素中的一个元素的地址,则p+1指向同一数组中的下一个元素地址。
指向下一个元素的值表达用*p++或*(p+1),但是不能用数组名*(a+1)表示,因为数组名是一个常量,不能这样使用。
C引用一个数组元素的方法
1)下标法。如 a[i] 形式;
2)指针法。如*(p+i)或 *(a+i)。其中 a 是数组名,p 是指向数组元素的指针变量,起初值 p=a。
实例:用指针实现逆序数组的输出
void nixu(int a[],int len){//定义数组指针指向aint *p = a;//定义下标int i = 0, j = len - 1;int temp;while (i<j){temp = *(p+i);*(p + i) = *(p + j);*(p + j) = temp;//修改下标i++, j--;}}int main(int argc, const char *argv[]){int a[6] = { 3, 5, 8, 4, 9, 7 };//调用逆序函数nixu(a, 6);//遍历数组for (int i = 0; i < 6; i++){printf("%d ", a[i]);}printf("\n");return 0;}
4、一维指针数组
定义:一个数组的元素的值为指针就是指针数组。
形式:类型说明符 *数组名[数组长度] 即:int *a[3]={&a,&b,&c};
如:int *a[3];//表示的是一个指针数组,有3个元素,每个元素是一个指针,且都指向整型变量
int a=3,b=4,c=5;int *p[3]={&a,&b,&c};
打印输出指针数组第一个元素的值可以用&a,p[0]表示;
而打印输出指针数组第一个元素的地址可以用&p[0],p表示;
5、数组名访问二维数组
定义一个二维数组int a[i][j];
则a代表的是第0行的首地址,a+i代表的是行号为i行的首地址;
行指针可以表示为:a+1,a[1],*(a+1)=&a[1][0];
列指针可以表示为:a[0]==&a[0][0],a[0]+1==&a[0][1].
总结:a[i]+j代表的是a[i][j]的地址,*(a[i]+j)获取的是a[i][j]的值,
此外(*(*a+i)+j)代表a[i][j]的值,且(*(*a+i)+j)==*(a[i]+j)。
6、二维数组指针
形式:数据类型 (*指针变量名)[二维数组列数],行指针越来指向二维数组的每一行,存放的是行的首地址。
例:int a[2][3]; int (*p)[3]=a=&a[0]=&a[0][0]=a[0];
这儿要注意它和一维指针数组的区别使用。
7、字符串指针
它存放的是每个字符串的首地址。
形式:char *变量名=“字符串内容”;字符串内容是常量。
字符指针变量和字符数组的关系
1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第一个字符的地址)
2)赋值方式。对字符数组只能对各个元素赋值,
char str[]="Hello world!";//字符数组赋值方式,它可以在定义时整体赋初值,但不能在赋值语句中整体赋初值。如:str[]="Hello world!"这样赋初值是不行的。
char *a; a="Hello world!";//字符指针变量的赋值方式,a是字符串第一个元素的地址。
3)对字符指针变量赋初值。
char *a="Hello world!";等价于 char *a; a="Hello world!";//字符指针变量可以在赋值语句中整体赋初值。
4)若定义了一个字符数组,在编译时为它分配了内存单元,他有确定的地址,但是字符指针变量若未对它赋初值,则它将指向一个不确定的字符数据。
5)指针变量的值可以改变,但是字符数组名不能改变。
char *a="Hello world!"; a=a+7;
6)用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串。
char *format="a=%d,b=%f\n";
printf(format,a,b);
例:对字符串排序,按照升序方式。
void sortstring(char *a3[],int len){//冒泡排序char *temp;//临时存放地址for (int i = 0; i < len-1; i++){for (int j = 0; j < len - 1 - i; j++){//比较字符串大小用函数if (strcmp(a3[j], a3[j + 1])>0){//实现交换temp = a3[j];a3[j]=a3[j+1];a3[j + 1] = temp;}}}}int main(int argc, const char *argv[]){//输入5个字符串并按字母顺序排列char *a3[5] = { "wer", "ad", "fgg", "rt", "bg" };for (int i = 0; i < 5; i++){printf("%s\n", a3[i]);}printf("\n");sortstring(a3, 5);for (int i = 0; i < 5; i++){printf("%s\n", a3[i]);}return 0;}
总结:指针和数组结合起来使用是非常有用的,也是一个重点难点,要好好体会。
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
- 黑马程序员_C语言基础_指针
- 黑马程序员_C语言_指针
- 黑马程序员_C语言指针
- 黑马程序员_C语言指针
- 黑马程序员_C语言01_基础总结
- 黑马程序员_C语言01_基础总结
- 黑马程序员_C语言01_基础总结
- 黑马程序员_C语言学习笔记之指针基础
- 黑马程序员_C语言基础
- 黑马程序员_C语言基础
- 黑马程序员_C语言_循环结构
- 黑马程序员_C语言_数组
- 黑马程序员_C语言_字符串
- 黑马程序员_C语言_数据类型总结
- 黑马程序员_C语言_预处理指令
- 黑马程序员_C语言指针的学习
- 黑马程序员_c语言的基础语法
- 黑马程序员_C语言基础_关键字、printf函数、scanf函数
- Multiply Strings
- Linux 之Cut命令详解
- 干货 IOS设备分辨率一览
- Combination Sum III
- jsp怎样实现动态表格
- 黑马程序员_C语言基础_指针
- 对文东山老师移植最新U-boot的总结
- 小胖说事34-----iOS UIImageView 的contentMode属性应用
- eclipse操作经验总结
- STL之hashtable源码剖析
- Linux负载均衡软件LVS之一(概念篇)
- HDU_3746Cyclic Nacklace
- The Log(我所读过的最好的一篇分布式技术文章)
- centos下hadoop集群搭建详细过程