目录
1.字符指针
2.指针数组
3.数组指针
3.1.创建数组指针
3.2.&数组名和数组名
1.字符指针
int main()
{
char ch ='w';
char* pc =&ch;
const char *p = "abcdef";//常量字符串 产生的值就是首元素的地址
//常量字符串不能被修改 因此需要加上一个const
printf("%s", p);
//打印字符串,只要有字符串的起始位置就可以了,不用解引用如果解引用打印的就是a.
return 0;
}
//*p = 'a';//如果加上这一行,程序不会报错但是会崩溃
内存中的放置是
指针指向是字符串首个元素的地址
字符串和数组本质上是差不多的,都是在内存中连续存储的。但是整型数组是无法依靠一个%s将数组完全输出,因为数组中没有'\0'和0停止字符。
例题
#include <stdio.h>
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
char *str3 = "hello bit.";
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;
}
2.指针数组
指针数组是用来存放指针的数组。
int* arr1[10]; //整形指针的数组
char *arr2[4]; //一级字符指针的数组
char **arr3[5];//二级字符指针的数组
举例1
int main()
{
//存放字符指针的数组,指针数组
const char* arr[5] = { "abcdef","未经遗憾寒彻骨","怎得梅花扑鼻香","123456" };
int i = 0;
for (i = 0; i < 4; i++)
{
printf("%s\n", arr[i]);
}
return 0;
}
举例2
#include <stdio.h>
int main()
{
//使用一维数组和指针数组来模拟二维数组
//1、创建一维数组
int arr1[4] = { 1,2,3,4 };
int arr2[4] = { 2,3,4,5 };
int arr3[4] = { 3,4,5,6 };
int arr4[4] = { 4,5,6,7 };
//2、创建指针数组
int *arr[4] = { arr1,arr2,arr3,arr4 };
//3、采用循环的方式打印数组
int i = 0;
for (i = 0; i < 4; i++)
{
int j = 0;
for (j = 0; j < 4; j++)
{
//printf("%d ",(*arr[i]+j) );上述的写法和下述的写法在规则上含义是相同的
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
3.数组指针
引入
字符指针—存放字符地址的指针—指向字符的指针 char*
整型指针—存放整型地址的指针—指向整型的指针 int*
浮点型指针—存放浮点型地址的指针—指向浮点型的指针 float*
数组指针——存放数组地址的指针—指向数组的指针,指向的整个数组,因此数组指针是一个指针。
3.1.创建数组指针
int main()
{
int a = 10;
int *pa = &a;
int arr[10] = { 0 };
int * pa1[10] = &arr;//会报错的哦
//等号前面前面的是指针数组,其中存储的类型是int * ,和&arr数组指针不同类型
int (*pa2)[10] = &arr;//数组指针,在去掉pa之后
//int(*)[10] = &arr;表示类型是数组指针 arr是数组的名字 int[10]是数组的类型
return 0;
}
上述程序会报错的哦。
char arr[5];
char(*pc)[5] = &arr;//数组的指针必须有数据类型和数组元素个数,这就是数组的类型
数组指针的用法较为鸡肋加深印象
int main()
{
//创建数组
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//创建数组指针
int(*pa)[10] = &arr;
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", (*pa)[i]);
}
return 0;
}
数组指针解引用之后就可以得到整个数组了
打印二维数组的话,会比较方便一点,这里要先知道二维数组的名字是第一行一位数组的数组指针。
#include <stdio.h>
void Print(int str[3][4])
{
int i = 0;//行数
for (i = 0; i < 3; i++)
{
int j = 0;//列数
for (j = 0; j < 4; j++)
{
printf("%d ",(*(str+i))[j] );
//[]的优先级比*优先级高,因此外部再加一个括号提高优先级
//(*(str + i))[j] 和str[i][j]两者是一样的
}
printf("\n");
}
}
int main()
{
//创建一个完整的二维数组
int arr[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
//使用函数传址来打印
Print(arr);
return 0;
}
3.2.&数组名和数组名
结论:&数组名是整个数组的地址,数组名就是首元素的地址
int main()
{
int arr[10] = { 0 };
//数组名字
printf("%p\n", arr);
printf("%p\n", arr+1);
//数组的首元素地址
printf("%p\n", &arr[0]);
printf("%p\n", &arr[0]+1);
//数组指针 &数组名
printf("%p\n", &arr);
printf("%p\n", &arr+1);
return 0;
}
上述&arr+1跳过的是整个字符,因此&arr取出的指针,指向的是整个数组。
int arr[5]; //整型数组,存储5个元素
int *parr1[10]; //指针数组,存储指针数据10个
int(*parr2)[10]; //数组指针,parr2是指针变量,指向的是数组int[10] ,有10元素,
int(*parr3[10])[5]; //数组指针,指针变量是parr3[10],指向的是int[5],
//相当于有一个int [10],每一个元素中装一个int[5]的地址,
int(*parr3[10])[5];图解
4.数组传参和指针传参
5.函数指针
6.函数指针数组
7.指向函数指针数组的指针
8.回调函数
9.指针和数组面试题的解析