在C语言基础阶段,我们学习过指针相关的一些基础内容,比如说:
1.指针是一个变量,用来存放地址,地址是唯一标识一块内存空间
2.指针的大小是固定的4 / 8个字节(32位平台 / 64位平台)
3.指针是由类型,指针的类型决定了指针的 + -整数的步长,指针解引用操作时候的权限
4.指针的运算
本篇文章及后面的几篇文章将会更加详细的去介绍和学习指针的进阶部分。(指针的内容在数据结构中会经常用到,所以一定要好好学习,打好基础~)
文章目录
1、字符指针
在指针的类型中我们知道有一种指针类型为字符指针char*;
一般使用方式:
这种方式通过字符指针解引用改变原字符变量的内容。
实际上,字符指针也可以这样使用:
这种方式是将字符串的首地址放到指针中,通过指针可以找到该字符串(千万不要理解成将字符串放到指针里面去,这是不可能的)。(类似与数组名就是首元素地址,但是跟数组还是有所区别的,这个字符串是一个常量字符串,无法被改变,如下图:)
如果说我们想修改这个字符串,需要将其放入数组中,然后再去修改:
扩展:在C语言中,内存可以被划分为栈区、堆区、静态区、常量区。
栈区:局部变量,函数形参,函数调用
堆区:动态内存如malloc等申请使用
静态区:全局变量,static修饰的局部变量
常量区:常量字符串
常量区中的内容在整个程序的执行期间是不允许被修改的,且同一份常量字符串只会创建一份,不会重复创建存储。
请看以下代码,猜猜输出结果是什么?
#include<stdio.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdef";
char* p1 = "abcdef";
char* p2 = "abcdef";
if (arr1 == arr2)
{
printf("arr1 == arr2\n");
}
else
{
printf("arr1 != arr2\n");
}
if (p1 == p2)
{
printf("p1 == p2\n");
}
else
{
printf("p1 != p2\n");
}
return 0;
}
分析:
创建数组需要开辟空间,数组arr1和arr2在内存空间所在位置是不同的,所以arr1 != arr2; char* p1 = “abcdef”; char* p2 = “abcdef”; "abcdef"是常量字符串,不能被修改,在内存空间所占位置固定,char * p1 = “abcdef”; 是将该常量字符串的首地址放到字符指针p1中,char* p2 = “abcdef”;
是将该常量字符串的首地址放到字符指针p2中。也就是说p1和p2存放都是常量字符串"abcdef"的首地址,所以 p1 ==p2。(注意:同样的常量字符串只会存一份,不会同时存两份,所以不会开辟不同的空间来存储。)
char* p2 = “abcdef”; 这种写法本身也不严谨,严谨的写法应该是:
const char* p2 = “abcdef”; (指向常量字符串的指针最好加上const!)
总结:这里arr1和arr2指向的是一个同一个常量字符串。
C /C++会把常量字符串存储到单独的一个内存区域当几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以arr1和arr2不同,p1和p2相同。
2、指针数组
指针数组是一个存放指针的数组
int* arr1[5];
char* arr2[5];
double* arr3[5];
整型数组-- - 存放整型的数组
int arr4[10];
字符数组-- - 存放字符的数组
char arr5[10];
看以下代码,猜猜结果是什么?
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = 30;
int* arr[3] = {
&a, &b, &c };
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d ", *arr[i]);
}
return 0;
}
我们知道数组名可以代表首元素的地址,请看下面这段代码:
#include<stdio.h>
int main()
{
int arr1[] = {
1,2,3 };//arr1--int*
int arr2[] = {
4,5,6 };//arr2--int*
int arr3[] =