C 语言 指针
一、指针
1.几个概念
- 指针:指针就是一个地址
- 指针变量:指针变量是用来存放指针(一个地址)的变量
- 指针变量与普通变量的区别:普通变量存放的是数据,指针变量存放的是地址
- 指针变量的类型:存放的地址指向的数据的数据类型
2.取地址运算符和取值运算符(取值与取址)
如果需要获取某个变量的地址,可以使用取地址运算符 (&)
如果需要访问指针变量指向的数据,可以使用取值运算符 (*)
3.指针的声明和赋值
类型名 *指针变量名
eg: char *pa; eg: int *pb;
申明并赋值
#include<stdio.h>
int main(){
char a = 'F';//这是声明一个普通变量,a存放的就是字符F
char *pa = &a;//这是声明一个指针变量pa,并将a的地址存放在指针变量pa中
//注意赋值时等号(=)的右边必须为一个地址
//char *pa = a;//由于a不是一个地址,所以这种赋值是错误的
printf("a的地址为:%p\n",&a);
printf("pa的值为:%p\n",pa);
return 0;
}
申明后赋值
#include<stdio.h>
int main(){
char a = 'F';//这是声明一个普通变量,a存放的就是字符F
char *pa;//这里只声明了一个指针变量,还没赋值
//错误初始化:*pa = &a;//因为指针变量pa已经声明,所以此处不该有*号,有*号意味着修改指针的值,要避免访问未初始化的指针
//错误初始化:*pa = a;//因为指针变量pa已经声明,所以此处不该有*号,有*号意味着修改指针的值,要避免访问未初始化的指针
pa = &a;//正确初始化,将a的地址赋值给指针变量pa
return 0;
}
避免访问未初始化的指针
int main(){
int *a;//此处的指针没有被初始化
*a = 123;//间接访问很危险
return 0;
}
4.修改指针的值
#include <stdio.h>
int main(){
//定义两个普通变量
char a = 'F';
int f = 123;
//定义两个指针变量
char *pa = &a;
int *pb = &f;
//打印指针变量指向的值
printf("a = %c\n",*pa);//F
printf("f = %d\n",*pb);//123
//修改指针变量指向的值
*pa = 'C';
*pb += 1;
//打印修改后的指针变量指向的值
printf("now,a = %c\n",*pa);//C
printf("now,f = %d\n",*pb);//124
//打印修改后的变量的值
printf("now,a = %c\n",a);//C
printf("now,f = %d\n",f);//124
//打印指针变量占用的内存空间
printf("sizeof pa = %d\n",sizeof(pa));//8
printf("sizeof pb = %d\n",sizeof(pb));//8
//打印指针变量指向的地址
printf("the addr of a = %p\n",pa);//0x7ffee6cb19ab(每次都不一样)
printf("the addr of f = %p\n",pb);//0x7ffee6cb19a4(每次都不一样)
return 0;
}
二、指针和数组
1.数组名其实是数组第一个元素的地址
#include <stdio.h>
int main(){
char str[128];//定义一个字符数组
printf("请输入域名:");//shuidi.cn
scanf("%s",str);//数组名其实是数组第一个元素的地址,所以这里不用&符号
printf("域名为:%s\n",str);//shuidi.cn
//这个例子说明:
//1、数组名其实是数组第一个元素的地址
printf("str的地址是:%p\n",str);//0x7ffee3bfe920(每次都不一样)
printf("str第一个元素的地址是:%p\n",&str[0]);/0x7ffee3bfe920(每次都不一样)
return 0;
}
2.指针的运算
当指针指向数组元素的时候,我们可以对指针变量进行加减运算,这样做的意义相当于指向距离指针所在位置向前或向后第n个元素 对比标准的下表法访问数组元素,这种使用指针进行间接访问的方法叫做指针法
3.指针和数组的区别
数组名只是一个地址,而指针是一个左值
#include<stdio.h>
int main(){
char str[] = "shuidi.cn";
char *pa = str;
int count = 0;
//++的优先级高于*,所以此处是先将地址+1再取值
while(*pa++ != '\0'){//此处不能直接使用str++,因为str是数组名字,不是左值;
count++;
}
printf("一共有%d字符\n",count);
return 0;
}
三、指针数组和数组指针
1.数组指针(指针)
数组指针是一个指针,它指向的是一个数组
定义:int (\*pa)[5];//[]
的优先级大于 *
,但是 ()
的优先级与 []
一样,但是结合是从左到右
#include<stdio.h>
int main(){
int temp[5] = {1,2,3,4,5};
int (*p1)[5] = &temp;
int i;
for(i=0;i<5;i++){
printf("%d\n",*(*p1+i));
}
return 0;
}
2.指针数组(数组)
指针数组是一个数组,每个数组元素存放一个指针变量
定义:int *pa[5];//[]
的优先级大于 *
#include<stdio.h>
int main(){
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;
int *p1[5] = {&a,&b,&c,&d,&e};
int i;
for(i=0;i<5;i++){
printf("%d\n",*p1[i]);
}
return 0;
}
int main(){
char *p1[5] = {
"aaaa",
"bbbb",
"cccc",
"dddd",
"eeee"
};
int i;
for(i=0;i<5;i++){
printf("%s\n",p1[i]);
}
}
3.指向数组的指针
#include <stdio.h>
int main(){
int temp[5] = {1,2,3,4,5};
int *p = temp;
int i;
for(i=0;i<5;i++){
printf("%d\n",*(p+i));
}
}
四、指针和二维数组
c 语言中并没有正真的二维数组,二维数组是通过线性扩展的方式实现
# include <stdio.h>
int main(){
int a[2][3] = { {1,2,3},{4,5,6} };
int i;
int j;
printf("二维数组a的地址:%p\n",a);
printf("二维数组a[0]的地址:%p\n",a[0]);
printf("二维数组a[0][0]的地址:%p\n",&a[0][0]);
printf("*(a+1)=%d\n",**(a+1));//语法糖:*(a+1) = a[1]
for(i=0;i<2;i++){
for(j=0;j<3;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
return 0;
}
五、void 指针和 NULL 指针
1.void 指针
void 指针我们把它称之为通用指针,就是可以指向任意数据类型的。也就是说,任何类型的指针都可以赋值给 void 指针
#include<stdio.h>
/**
将void类型的指针指向为其他类型的指针就需要强制转换
*/
int main(){
int num = 1024;
int *pa = #
char *pb = "shuidi";
void *pc;
pc = pa;
printf("pa:%p,pc:%p\n",pa,pc);
printf("pa=%d,pc=%d\n",*pa,*(int *)pc);//注意强制转换
pc = pb;
printf("pb:%p,pc:%p\n",pb,pc);
printf("pb=%s,pc=%s\n",pb,(char *)pc);
return 0;
}
2.NULL 指针
NULL 代表该指针不指向任何东西
- 当你还不清楚要将指针初始化为什么地址时,请将它初始化为NULL;
- 在对指针进行解引用时,先检查该指针是否为NULL。
- 这种策略可以为你今后编写大型程序节省大量的调试时间。
#include <stdio.h>
int main(){
int *pa;
int *pb = NULL;
printf("%d\n",*pa);
printf("%d\n",*pb);
return 0;
}
/**
NULL 不是 NUL(表示空字符'\0')
**/
六、指向指针的指针
#include <stdio.h>
int main(){
int num = 520;
int *p = #
int **pp = &p;//pp就是指向指针的指针(pp里面存放的是指针的地址)
printf("num:%d\n",num);
printf("*p:%d\n",*p);
printf("**pp:%d\n",**pp);
printf("&p:%p,pp:%p\n",&p,pp);
printf("&num:%p,p:%p,*pp:%p\n",&num,p,*pp);
return 0;
}
int main(){
//定义一个数组指针
char *cBooks[] = {
"《C程序设计语言》",
"《C专家编程》",
"《C和指针》",
"《C陷阱与缺陷》",
"《C Primer Plus》",
"《带你学C带你飞》"
};
//定义一个指向指针的指针
char **byFishC;
//定义一个
char **jiayuLoves[4];
int i;
byFishC = &cBooks[5];
jiayuLoves[0] = &cBooks[0];
jiayuLoves[1] = &cBooks[1];
jiayuLoves[2] = &cBooks[2];
jiayuLoves[3] = &cBooks[3];
printf("FishC出版的图书有:%s\n",*byFishC);
printf("小甲鱼喜欢的图书有:\n");
for(i=0;i<4;i++){
printf("%s\n",*jiayuLoves[i]);
}
return 0;
}
int main(){
int array[10] = {0,1,2,3,4,5,6,7,8,9};
int *p = array;
int i;
for(i=0;i<10;i++){
printf("%d\n",*(p+i));
}
printf("-----------\n");
int a[3][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
int m,n;
for(m=0;m<3;m++){
for(n=0;n<4;n++){
printf("%d ",*(*(a+m)+n));
}
printf("\n");
}
int (*q)[4] = a;
for(m=0;m<3;m++){
for(n=0;n<4;n++){
printf("%d ",*(*(q+m)+n));
}
printf("\n");
}
return 0;
}
七、指向常量的指针
#include <stdio.h>
//定义常量
#define PI 3.14
int main(){
//还可以使用const关键字将一个变量变为常量
int a = 1;
const int b = 2;
a = 2;//此时可以修改变量a
printf("%d\n",a);
//b = 1;//此时不能修改用const关键字定义的变量
printf("%d\n",b);
//指向常量的指针
int num = 520;
const int cnum = 880;
const int *pc = &cnum;
printf("cnum:%d,&cnum:%p\n",cnum,&cnum);
printf("*pc:%d,pc:%p\n",*pc,pc);
//*pc = 1024;//不允许
pc = #//这个是可以的
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Phpstorm 配置 xdebug
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论