众所周知,指针是c语言的灵魂所在,也是c语言的难点所在,很多人在学习这部分的时候都感到非常困难,然而只要你静下心来慢慢“品尝”,你会发现,指针非常的灵活,C语言之精髓!!
指针是什么?这个问题听起来真的不陌生,可能你自己都常常问你自己指针到底是什么?
---------指针就是地址,地址就是指针
我们可以把计算机内存用一个方块来模拟,把这个方块切成若干个,每一块大小为一个字节(八个比特位),每一块用一个数来标识(地址),当我们想找到某一块时只需要知道这一块的标识数(地址),由于这个标识数(地址)具有很强的指向性,所以我们称它为指针。
那么“指针变量”又是什么呢,指针变量是我们定义的一个变量,这个变量用来存放指针
实际上,我们不要去纠结这两个名词,我们把指针变量一般就叫指针,区分它们并没有实际意义。
一、字符指针
char ch = 'a';
char* p =&ch;
printf("%c", *p);
图中的p就是一个字符指针,下面来看另一种常用字符指针
char* p = "i love you";
printf("%s\n", p);
这里的p也是一个字符指针,那么这个指针到底是啥?如果我们直接用%p打印出p,我们将得到一个地址,那麽这个地址到底是谁的地址呢?对,他就是首字符的地址,在这里即是i的地址。
下面来看一道经典例题:
char str1[] = "i love you";
char str2[] = "i love you";
char* str3 = "i love you";
char* str4 = "i love you";
if (str1 == str2)
printf("1 and 2 is same\n");
if (str3 == str4)
printf("3 and 4 is same\n");
输出结果为:3 and 4 is same
那为什么会这样呢?
因为这里的str3和str4指向的是同一个字符串,c/c++会把字符常量单独放到一个区域(字符常量区),当要用到他们时,就可以用指针解引用来使用它们。理所当然,这里的str3和str4不能再被更改否则会报错。 str1和str2都是数组,在C语言中,两个数组的地址(数组名)怎么可能相等呢,编译器不可能给他们开辟在同一个地址空间,所以这里肯定不一样呗!!!
二、指针数组和数组指针
很显然,指针数组是数组, 数组指针是指针
那他们的用途分别是什么呢?
指针数组:
定义:
int* arr1[10]; //存放整形指针
char* arr2[10]; //存放字符指针
这里指针数组不再过多介绍,我们前面有一篇文章专门介绍了指针数组和数组指针,里面还有一些经典例子。
数组指针:
定义:
int (*p1)[10];
char (*p2)[10];
这里就有一些小伙伴开始搞不清楚数组指针和指针数组的写法,真的很像耶✌!!这里有一个小诀窍来辨别他们:我们得知道[ ]的优先级高于 * ,所以没加括号时会与[ ]先结合,那麽他就是一个数组(指针数组),而括号括起来后,他就是一个指针(数组指针);
知识法宝:定义一个数组arr,区别arr和&arr
有人会一本正经的回答,它两不就一样嘛!确实,他俩的值都一样,但意义却大不相同,你需要切记:数组名“永远”代表数组首元素的地址(除1. 用sizeof求取它的长度 2.取地址数组名这两种特殊情况外)。而&arr代表这个数组的地址。
你可以打印出 arr+1 和 &arr+1 的值,他们的值是不会相同的!!
下面看这几条语句:
int arr[10] = {0};
int (*p1)[10];
int (*p2)[8] = &arr; //警告 (纬度应该一致)
p1 = &arr;
p1 = arr; //警告 (应该取该数组的地址,而不是首元素的地址)
好了,那么数组指针一般的用途到底是啥?我们看下面的代码:
#include<stdio.h>
void print(int (*p)[3], int row, int col);
int main()
{
int arr[2][3] = {{2,3,4},{5,6,7}};
print(arr, 2, 3);
return 0;
}
void print(int (*p)[3], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
printf("%d ", p[i][j]);
printf("\n");
}
}
结果为:
这是数组指针的一个典型运用,用它来传参多维数组,这里该怎样使用它来传参呢?
切记下面的话:
数组 传参 会 降维 成 “指向其内部元素” 的 指针;
当多维数组传参时,用数组名接收时,只能省去离数组名最近的那个纬度;
三、指针传参:
一级指针传参
可以用来接收一维数组、一级指针等等,这里比较简单,不再过多介绍
二级指针传参:
下面看一段代码:
#include<stdio.h>
void test(char** p)
{
printf("lalala\n");
}
int main()
{
char c = 'b';
char* pc = &c;
char** ppc = &pc;
char* arr[10];
test(&pc);
test(ppc);
test(arr);
return 0;
}
该代码体现了几种二级指针的传参(该代码无警告无错误)