指针,作为C语言的一个特色,其在C语言当中有着不可或缺的作用。想要学好C语言,指针是必须要掌握的重要知识点。
作为C语言初学者,我们已经知道指针的基本概念:
1.指针是一个变量,用来存放地址,地址唯一标识一块内存空间。
2.指针的大小是4/8个字节(分别为32位/64位操作系统)。
3.指针有类型,指针的类型决定了指针+-整数的步长、指针解引用操作时的权限。
4.指针可以进行运算
当然,指针肯定不仅仅有上面这些内容,今天我们就来一起深入探讨指针。
- 字符指针
字符指针,顾名思义,就是指向字符的指针,类型为char*
字符指针的取地址解引用操作同整形指针的一样:
int main()
{
char ch='w';
char *pc=&ch;
*pc='w';
return 0;
}
还有一种使用方式:
int main()
{
const char* pstr="hello world"; //这里的const可以省略,但是在高版本编译器下可能会报警告
printf("%S",ptsr);
return 0;
}
输出结果是这样的:

光看代码我们也许容易误解,误以为是将hello world这一字符串放到字符指针pstr里了,然而,存放进字符指针pstr里的,本质上只是字符串hello world的首字符地址。通过首字符地址,就可以找到一整个字符串。
为什么上面注释说道const可以省略呢?
来看这样一道面试题就能更加透彻的理解:
#include <stdio.h>
int main()
{
char str1[] = "hel1lo World";
char str2[] = "hel1lo World";
const char *str3 = "hello World";
const char *str4 = "hel1o World";
if(str1 ==str2)
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");
if(str3 ==str4)
printf("str3 and str4 are same\n" );
else
printf("str3 and str4 are not same\n");
return 0;
}
运行结果是这样的:

原来,通过字符指针存放字符串的方式,存放的字符串是常量字符串,也就是说,这里的str3和str4指向的是同一个常量字符串。c/c++通常会将常量字符串存储到一个单独的内存区域,当几个不同的指针指向同一个字符串的时候,实际指向的都是同一块内存。但是如果用相同的常量字符串去初始化不同的数组的时候,就会开辟出不同的内存空间。所以在这里str1和str2不同,str3和str4相同。
正是因为常量字符串这一属性,所以正确的写法应该是const char *str3 = "hello World",但我们既然已经知道这里的字符串是常量字符串,为了方便这里的const就可以省略,写成char *str3="hello world"也是正确的。
- 指针数组
指针数组,就是用来存放指针的数组。
如果能够理解整形数组、字符数组等概念,指针数组也就很好理解。
来看以下几个例子:
int *arr[10]; //可以存放10个整形指针的数组
char *arr2[5]; //可以存放5个字符指针的数组
char **arr3[7]; //可以存放7个一级字符指针的二级字符指针的数组
- 数组指针
3.1数组指针的定义
顾名思义,数组指针就是能够指向数组的指针。
数组指针的形式是这样的:
int (*p)[10];
这里,p先跟*结合,表示p是一个指针变量,然后指向一个大小为10个整形的整形数组。所以p是一个指向数组的数组指针。
由于[]的优先级高于*,所以必须用()来保证p先于*结合,否则就是这样的
int *p[10];
这样就成了一个指针数组。
数组指针的类型是怎样的呢?
假如我们现在创建一个整形指针int *p1,我们可以很清楚的知道p1是一个指针,类型为int *。
那么类比到数组指针,对于int (*p)[10],p的类型就是int (*)[10];
所以可以得到一个判断变量类型的简单方法,去掉变量名以后剩下的部分就是该变量的类型。
3.2数组指针的使用
数组指针既然指向数组,那么指针中存放的就应该是数组的地址,如下:
#include <stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int (*p)[10]=&arr;
return 0;
}
这样就实现了一个简单的取地址操作。如果想要通过数组指针打印数组内容,代码如下:
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", *(*p)+i);//*p表示arr,也就是数组首元素地址,*((*p)+i)即是*(arr+i)
}
return 0;
}
打印结果如下:

(本篇完)