吾乃比克大魔王,有趣的人类为何不和我一起奋战难题!
导入:
!!!!!!!!!!!!
本大魔王很愿意跟你们分享进入所学的新知以及自己的理解,接下来本王要跟你分享,请认真听. 照顾一些学了汪的人,基本指针的引入:要知道指针的本质是地址,但是我们日常说的指针指针其实是某个地址的变量名。比如 int a; int*p=&a; 我们取地址操作符 取出来a的地址,用p这个变量来存储,指针变量的类型为int *型; 所以我们接下来需要使用到地址的时候,小笨蛋们千万注意不要写成*p了 这个时候的*就是访问p地址对应的内容了。而是直接写成p。
作为本王的我还是担忧你不理解呢!还是举个简单的例子吧;比如创建了一个数组,如下:
char str[20]="bi te da mo wang";
char*s = &str[0];
prntf("%s",s);//显然这里s指向的是s首元素的地址,printf函数会根据指定的地址然后遍历打印该地址//后面的元素,直到遇到\0
目录
一.指针运算
#include<stdio.h>
int my_strlen(char* p, int s)
{
char* last = p + s;
return last-p;
}
同样可以用指针解引用的形式去写
int my_strlen(char* str, int s)
{
int count = 0;
//访问到\0的ascll码值是0
while (*str)
{
count++;
str++;
}
return count;
}
int main()
{
//基本指针概念运用
//我们通常说的指针是它存放地址的变量名,实际上指针就是地址 ,比如我们说某某某的指针,其实就是它地址
//指针的类型决定它加减整数移动的一格对应多少字节 ,其大小跟对应的存放的地址的内容有关,这就是其中的内存
//指针减指针得到的是这两个指针之间的元素
//eg: 设计一个函数模仿 strlen函数
char str[] = "wo hao shuai";
int sz = sizeof(str) / sizeof(str[0]);
int r = my_strlen(str,sz);
printf("%d",r);
return 0;
}
字符指针的创建
void main()
{
//我们最常见的字符指针的创建如下:
char str[] = "bi ke da mo wang";
char* pa = str;//特别注意这里的str数组名一般就是首元素地址 指向的是b
//但是实践上,还有一种字符指针的创建让你大吃一惊
char* pm = "wo si bi ke ";
char* pd = "wo si mo wang";
//这里上面两个指针指向的是字符串吗?
// 不,而是他们对应的字符串第一个元素‘w‘这里可以用图来理解 如图:
}
既然知道了,本王提示一下 再给一个大惊喜 : 对于这串单独的字符串的出现它的内存有点像数组是连续存放的
试试
void main()
{
char* pm = "wo si bi ke ";
// char* pd = "wo si mo wang";
printf("%s",pm);
}
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char* str3 = "hello bit.";
const char* str4 = "hello bit.";
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;
}
二.指符指针
void main()
{
//我们最常见的字符指针的创建如下:
char str[] = "bi ke da mo wang";
char* pa = str;//特别注意这里的str数组名一般就是首元素地址 指向的是b
//但是实践上,还有一种字符指针的创建让你大吃一惊
char* pm = "wo si bi ke ";
char* pd = "wo si mo wang";
//这里上面两个指针指向的是字符串吗?
// 不,而是他们对应的字符串第一个元素‘w‘这里可以用图来理解 如图:
}
//既然知道了,本王提示一下 再给一个大惊喜 : 对于这串单独的字符串的出现它的内存有点像数组是连续存放的
//试试
void main()
{
char* pm = "wo si bi ke ";
// char* pd = "wo si mo wang";
printf("%s",pm);
}
某企业的笔试题目 小的们试试?
问输出结果是什么
int main()
{
char str1[] = "hello mo wang.";
char str2[] = "hello bit.";
const char* str3 = "hello mo wang.";
const char* str4 = "hello mo wang.";
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;
}
我们要理解本质 才能变得自信!
本王助你一臂之力吧!
上述代码首先将两串完全相同的字符串放到两个数组里面,首先呢我们要知道 第一个if语句里面的判断表达式子是(str1==str2)我们知道对于数组这两个数组来说他们所有元素的地址肯定是不一样的因为在数据存储的时候他们开辟的空间是独立的,所以对应的地址一定不一样,进一步说数组名是该数组首元素的地址,所以我们说这里str1 和str2 他们指向的地址肯定不一样只不过他们指向的内容都是‘h’ 但是这里的表达式 是两个指针的比较所以是假! 所以if语句不执行 执行else控制的语句
第二个if语句 这里有坑,本王给你补充一下,对于一串独立的字符串来说呢,你写出来的时候,他会根据自己的类型,在内存中乖乖的找到内存放下来,意味着它是一串常量字符串 所以说呢 人家是const char 你可不要误会了 所以你拿不同指针变量去指向他们地址的时候,虽然指针变量名不一样,但是指针变量指向的地址还是一样的哦! 所以第二个if执行
听懂请举手!
三.指针数组
好了好了 不要闹了 小的们 ,关键时刻到了 ,指针数组! 这可是一个难题!!!!!! 不吹牛皮了,我们直接上吧!
对于指针数组的理解,首先我们回顾一下数组,如:字符数组 整型数组
int arr[ ]={1,2,3,4,5};
char str [] = "bi ke da mo wang";
显然字符数组里面存放的是字符,整型数组里面放的是整型,所以指针数组里面放里面放的是指针 咯
在说指针数组的一些玩意之前我们说说:一级指针,二级指针 ,还有多级指针吧
比如一个简单的变量 int 型 啊 浮点型啊 什么的
补充指针变量创建时候的细节:如 int*pa; 这里的*其实指向后面的变量是一个指针。所以我们只是想单纯的调用指针的话就是pa 咯
3.1 指针数组的认识和创建
int a =0;
int* pa =&a;//我们把数据类型指向的变量存放到指针里面这就是一级指针
int **pa ; //我们都知道指针是放地址的所以,对于创建的变量也一定有地址 指针变量//也一样咯,所以用另一个指针存放一级指针的话 就叫做二级指针
聪明的你肯定想到三级指针了吧:那不就是存放二级指针的变量咯
好 问题来咯 现在 我创建一个数组 里面存放的是指针,也就是 创建了一个指针数组 如
int *arr[]={0};
很显然啦 问你,里面存放的指针类型是什么!
对照
int arr[]={0,1,2,3,4};
里面存放的是int 型 那么指针数组里面存放的计算 int*型的变量也就是一级指针咯
ok 接下来
3.2 指针数组的使用
void main()
{
int arr1[] = { 1,2,3,4 };
int arr2[] = { 5,6,7,8 };
int* pa1 = &arr1[0];
int* pa2 = &arr2[0];//分别创建一级指针存放他们各自首元素地址
int* arr[2] = { pa1, pa2 };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
}
这个输出结果理解 : 类似于 二级数组的感觉但是理解要这样理解 首先 arr中存放的是各自数组首元素的地址,然后 arr[i]指向的是哪个数组 ,然后才是 arr[i ][j] 这里的j是指对应的数组指向的第几个元素
魔王小妙招
切记 不可外传!
对于指针 这样使用 *pa是访问pa指针指向的内容
好 我们进一步说 p[ i]=*(p+i);
四.数组指针
4.1数组指针的认识和创建
数组指针,同样的我们想想,他是数组,还是指针呢?
ok 叫一句比克大魔王 我来教教你类比学习吧
//我们之前学过,整型指针 int * ,字符指针 char*
//他们指向的分别是整型, 字符
// 所以数组指针自然指向的是数组咯
对于 数组指针的创建 int *p []
* 表示指向的变量是指针变量 【】表示指向的是数组 int 表示数组内容是整型
注意特别注意 我上面的创建写法是错误的 为什么呢 因为 【】的结合性比*强 所以你还没来得及说p是给指针 【】就把你家的p带走了
说: 嘿 p 你不带括号跟我走了哟 你就是数组名了哈
好 好 好 接下来我们创建吧
4.1.1 数组指针引入
小的们,上面这串代码和输出结果,我们来一起了解一下便于你更好的对内存的的存储以及对指针的实现更好的理解:
首先 我们看看在内存中的数组长什么样,看 我们前面说过 对于指针的是指向内存的一个编号,我们可以通过指针来访问内存,我们这里根据下面了解到数组的内存分布是连续的。
来我们看看,对于&arr 得到的是整个数组的地址但是我们发现他的地址值呢居然和首元素地址arr是一样的,注意只是值一样,也就是说对于一个数组指针(这里是值数组地址)来说默认指向该数组首元素地址。 但是我们发现了吗&arr+1 居然跳过了几个字节呢 6*4 =24个字节而,arr+1 只跳过了4个字节,其实这里就说明&arr对应的指针和arr对应的指针是不一样的。&arr+1跳过的是整个数组的内存空间大小,而arr+1是访问数组的第二个元素的地址。
好了! 我们了解了很多关于指针的东西了,我们该真正认识数组指针咯
#include<stdio.h>
void print_arr1(int(*arr)[4], int x, int y)
{
printf("%d\n",arr[0][3]);
}
void main()
{
int arr[3] [4] = {0,1,2,3,4};
print_arr1(arr,3,4);//传递该数组的行和列
// 特别注意 这里arr 传递的是二维数组首元素地址 而二维数组的首元素地址是一维数组
//所以我们用一个指针来接收这个一维数组应该用数组指针来接收
return 0;
}
void test(int arr[10])//ok?
{}
//void test(int* arr)//ok?
//{}
void test2(int* arr[20])//ok?
{}
//void test2(int** arr)//ok?
//{}
int main()
{
int arr[10] = { 0 };
int* arr2[20] = { 0 };
test(arr);
test2(arr2);
return 0;
}
我们看看上面这串代码然后经过我们的调试,我们可以发现一个事情,arr2二维数组的名字作为首元素地址,他指向的类型是int*性的一级指针 ,所以证明了他传递的确实是第一行的一维数组。
后续还有函数指针回调函数,用冒泡排序实现qsort函数呢!小的们期待吗!!!