怎样熟练掌握c语言的指针(C语言基础知识最核心的)
怎样熟练掌握c语言的指针(C语言基础知识最核心的)int *a; ... *a = 12;上面这个代码段说明了一个极为常见的错误:我们声明了这个变量,但从未对它进行初始化,所以没法预测12这个值将存储于什么地方。如果变量是静态的,它会被初始化为0 ;如果变量是自动地,它根本不会被初始化。无论哪种情况,声明一个指向整型的指针都不会"创建"用于存储整型值的内存空间。int a = 12; int *pa = &a; printf("*pa:%u." *pa); // 输出是12; *pa = 14; // 此时a的值为14了这里需要注意的一点,也是我以前经常迷惑的一点:定义指针时,编译器并不为指针所指向的对象分配空间,它只是分配指针本身的空间,除非在定义时同时赋给一个字符串常量进行初始化。比如:指针的定义形式如下:datatype *name; 或 datatype *name = value;其意思就是n
指针是C语言最重要也是最难理解的部分,它在我们平时的工作中无处不在。
有人说学会了指针,C语言也就学会一半。为什么说指针难。因为指针与数组相结合就涉及数组指针与指针数组。指针与结构体结合就涉及结构体指针。指针与字符结合涉及字符指针。指针与const结合涉及常量指针与指针常量。指针与函数结合涉及函数指针与指针函数,同时也会涉及回调函数。指针和指针结合涉及到二维指针。
作者曾经因为上面的这些问题,困扰了许久。因而在网上找了许多的博客来解答疑惑。这篇文章,我试图将上面的知识点以例子的方式呈现给大家,我相信通过阅读本文,大家会对指针有更深一步的了解。文中涉及的例子均来源于网上。
1 指针的定义我们知道,普通的变量存储的是一个值。而指针变量,它存储的也是一个值,只是这是一个特殊的值:它的值是另一个变量的地址。
指针的定义形式如下:
datatype *name;
或
datatype *name = value;
其意思就是name是一个指针,它指向的是一个类型为dataype的地址。
指针存储的是一个地址,如果需要获取这个地址对应的内容 可以通过解引用符*获取:
int a = 12;
int *pa = &a;
printf("*pa:%u." *pa); // 输出是12;
*pa = 14; // 此时a的值为14了
这里需要注意的一点,也是我以前经常迷惑的一点:定义指针时,编译器并不为指针所指向的对象分配空间,它只是分配指针本身的空间,除非在定义时同时赋给一个字符串常量进行初始化。比如:
int *a;
...
*a = 12;
上面这个代码段说明了一个极为常见的错误:我们声明了这个变量,但从未对它进行初始化,所以没法预测12这个值将存储于什么地方。如果变量是静态的,它会被初始化为0 ;如果变量是自动地,它根本不会被初始化。无论哪种情况,声明一个指向整型的指针都不会"创建"用于存储整型值的内存空间。
但是 下面的定义创建了一个字符串常量(为其分配了内存):
char *p = "breadfruit";
始化指针时所创建的字符串常量被定义为只读。如果试图通过指针修改这个字符串的值,程序就会出现未定义的行为。
除了上述的定义是对的外,其他的定义都是错误的:
float *pip = 3.14; // 错误!无法通过编译
2 指针的运算
指针 (-) 整数指针存储的是一个地址,这个地址本质上是一个整数,所以可以加上或减去一个整数。但是它不是普通的加法或减法,指针加上或减去一个整数结果是另一个指针。但是,运算后的指针指向哪里呢?当一个指针和一个整数执行算术运算时,整数在执行加法(减法)运算前会根据合适的大小进行调整。这个"合适的大小"就是指针所指向类型的大小,"调整"就是把整数值和"合适的大小"相乘。
#include <stdio.h>
int main()
{
int a = 10;
int *pa = &a;
double b = 99.9;
double *pb = &b;
char c = '@';
char *pc = &c;
printf("sizeof(int)= %u sizeof(double)=%u sizeof(char)=%u\n"
sizeof(int) sizeof(double) sizeof(char));
//最初的值
printf("&a=%p &b=%p &c=%p\n" &a &b &c);
printf("pa=%p pb=%p pc=%p\n" pa pb pc);
//加法运算
pa ; pb ; pc ;
printf("pa=%p pb=%p pc=%p\n" pa pb pc);
//减法运算
pa -= 2; pb -= 2; pc -= 2;
printf("pa=%p pb=%p pc=%p\n" pa pb pc);
return 0;
}
运算结果:
sizeof(int)= 4 sizeof(double)=8 sizeof(char)=1
&a=000000000061FE04 &b=000000000061FDF8 &c=000000000061FDF7
pa=000000000061FE04 pb=000000000061FDF8 pc=000000000061FDF7
pa=000000000061FE08 pb=000000000061FE00 pc=000000000061FDF8
pa=000000000061FE00 pb=000000000061FDF0 pc=000000000061FDF6
由上面的结果可以看到,当对指针pa,pb,pc进行加1时,实际地址增加的是对应类型的大小。减法也一样。
指针 - 指针
只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针。两个指针相减的结果是两个指针之间的元素个数。比如 如果p1指向array[i]而p2指向array[j],那么p2-p1的值就是j-i的值。如果两个指针所指向的不是同一个数组中的元素,那么它们之间相减的结果是未定义的,也是毫无意义的。
3 指针与数组3.1 数组指针(指向数组的指针)数组指针,它是一个指针,指向的是一个数组。即它存的是一个数组变量的地址。所以这个指针每加一步的步长就是数组的长度。由于它每跨一步都是整个数组,所以又称行数组。
#include <stdio.h>
int main()
{
int a[3][4] = {{1 2 3 4} {5 6 7 8} {9 10 11 12}};
int (*pa)[4];
pa = a;
printf("a:%p &a:%p &a[0][0]:%p\n" a &a &a[0][0]);
printf("pa:%p (*pa)[0]:%u\n" pa (*pa)[0]);
pa ;
printf("&a[1]:%p &a[1][0]:%p\n" &a[1] &a[1][0]);
printf("pa:%p (*pa)[0]:%u\n" pa (*pa)[0]);
return 0;
}
运行结果:
a:000000000061FDE0 &a:000000000061FDE0 &a[0][0]:000000000061FDE0
pa:000000000061FDE0 (*pa)[0]:1
&a[1]:000000000061FDF0 &a[1][0]:000000000061FDF0
pa:000000000061FDF0 (*pa)[0]:5
首先,pa是一个数组指针,它首先存的是数组a的首元素的地址,由于数组名也是数组的首地址,所以a &a &a[0][0]的地址相同。pa中存的也是这个地址。然后对pa进行解引用,*pa之后得到这个数组,然后(*pa)[i]就是获得这个数组下标为i的元素。
3.2 指针数组指针数组,它本质上是一个数组,只不过整个数组存的类型是一个指针而已。
#include<stdio.h>
int main(void)
{
char *p1 = "Himanshu";
char *p2 = "Arora";
char *p3 = "India";
char *arr[3];
arr[0] = p1;
arr[1] = p2;
arr[2] = p3;
printf("\n p1 = [%s] \n" p1);
printf("\n p2 = [%s] \n" p2);
printf("\n p3 = [%s] \n" p3);
printf("\n arr[0] = [%s] \n" arr[0]);
printf("\n arr[1] = [%s] \n" arr[1]);
printf("\n arr[2] = [%s] \n" arr[2]);
return 0;
}
运行结果:
p1 = [Himanshu]
p2 = [Arora]
p3 = [India]
arr[0] = [Himanshu]
arr[1] = [Arora]
arr[2] = [India]
4 指针与字符
在C语言中,表示字符串一般有两种形式,一种是数组的形式,一种是字符指针的形式。
数组形式:
char arr[] = "hello world";
字符指针形式:
char *str = "hello world";
虽然上面两种形式都能表示字符串,但是它们还是有些区别的:
存储方式字符数组由若干元素组成,每个元素存放一个字符,而字符指针变量只存放字符串的首地址,不是整个字符串。
存储位置。数组是在内存中开辟了一段空间存放字符串 是存在栈区。而字符指针是在字面值常量区开辟了一段空间存放字符串,将字符串的首地址付给指针变量str。
赋值方式。对于数组,下面的赋值方式是错误的:
char str[10];
str="hello"; // 错误!
而对字符指针变量,可以采用下面方法赋值:
char *a;
a = "hello";
可否被修改。指针变量指向的字符串内容不能被修改,但指针变量的值(即存放的地址或者指向)是可以被修改的。
来源:稀土掘金,作者:Elec
对啦对啦!另外的话为了帮助大家,轻松,高效学习C语言/C ,我给大家分享我收集的资源,从最零基础开始的教程到C语言项目案例,帮助大家在学习C语言的道路上披荆斩棘!可以来我粉丝群领取哦~
编程学习书籍分享:
编程学习视频分享:
整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)最重要的是你可以在群里面交流提问编程问题哦!
对于C/C 感兴趣可以关注小编在后台私信我:【编程交流】一起来学习哦!可以领取一些C/C 的项目学习视频资料哦!已经设置好了关键词自动回复,自动领取就好了!