前言:
这次的指针数组结合乃作者呕心沥血之作,大家翻翻进度条就知道了,内容十分干货,各位读者若能全部耐心解析读懂了,想必也能理解掌握C语言中的数组指针这两把利剑了。
指针数组结合:
指针数组
概念:他是一个数组,该数组中每一个元素的类型是指针。
语法:
int * arr[ 元素数量 ] ; // 整型指针数组
char * arr[ 元素数量 ] ; // 字符指针数组
float * arr[ 元素数量 ] ; // 浮点指针数组
int * arr[ 元素数量 ] (int) ; // 函数指针数组
示例:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a = 123 , b = 456 , c = 789 , d = 111 , e = 222 ;
// 指针数组
int * arr1 [ 5 ] = {&a , &b , &c , &d , &e } ; // 整型指针数组
for (int i = 0; i < 5; i++)
{
printf( "arr1[%d]:%d\n" , i ,*arr1[i] );
}
// arr1[0][1] --》 *(arr1[0]+1) -- > *(*(arr1+0)+1)
printf("arr[0][1]:%d\n" , arr1[0][1] ) ;//得到数组首元素即*(&a+1),加一个&a大小,即指向&b,解引用得到456
printf("**arr:%d\n" , **arr1 ) ; // a = 123,arr1为数组首元素地址,解引用得到&a,再次解引用得到a的值123
printf("**arr1+1:%d\n" , **arr1+1 ) ; // a=124,同上,a的值加一得到124
printf("**(arr1+1):%d\n" , **(arr1+1) ) ; // b=456,arr1为数组首元素地址,+1偏移一个数组首元素地址大小,即指向数组第二个元素地址,解引用两次得到b的值
printf("*(*arr1+1):%d\n" , *(*arr1+1) ) ; // b =456,arr1为数组首元素地址,解引用得到&a,&a可以看作一个指针,+1偏移一个int地址大小,解引用得到b的值
printf("*(*arr1+1):%d\n" , **(&arr1+1) ) ; // 【越界】,&arr1为整个数组的地址,+1加一整个数组地址大小,指向数组之外,越界
printf("**(*(&arr1+1)-1):%d\n" , **(*(&arr1+1)-1) ) ; // e = 222,&arr1为整个数组的地址,+1加一整个数组的地址大小,解引用得到数组,指向数组
//末尾元素地址,-1减去一个数组元素地址大小,指向数组最后一个元素地址,两次解引用得到222
char * arr2 [ 5 ] ; // 字符指针数组
float *arr3 [ 5 ] ; // 浮点指针数组
// int * arr4 [ 5 ] (int) ; // 函数指针数组
return 0;
}
数组指针数组:
概念:他是一个数组,该数组中每一个元素都是指针,而这些指针指向的类型是数组类型。
语法:
type (* arr [5]) [N] ;
示例:
#include <stdio.h>
int main(int argc, char const *argv[])
{
// 整型数组
int arr1[2] ={1,2};
int arr2[2] ={10,20};
int arr3[2] ={100,200};
// 整型数组指针
int (*p1 )[2] = &arr1 ;
int (*p2 )[2] = &arr2 ;
int (*p3 )[2] = &arr3 ;
// 整型数组指针数组
int (* arr[3]) [2] = { p1 , p2 , p3} ;
// arr[i] --> p1
// p1 = &arr1
// (*arr[i]) --> (*p1) --> (*&arr1) --> arr1
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
printf("(*arr[%d])[%d]:%d\n", i , j , *((**(arr+i))+j) );
//(*arr[i])[j] --> *((*arr[i])+j) --> *((**(arr+i))+j))
//arr为数组首元素地址,+i加i个数组首元素地址大小,指向数组的第i+1个元素,第一次解引用得到数组的元素,即指针,再次解引用得到
//指针指向的值,即一维数组,这时候得到一维数组arr1即首元素地址,+加上j个数组首元素地址大小,偏移j个元素,解引用得到一维数组的元素
//这里会逐个打印出一维数组的全部元素
}
}
return 0;
}
指针数组数组:
概念:他是一个数组,该数组中每一个元素都是数组,而这些数组中每一个元素都是指针。
语法:
type * arr[3] [2] ;
数组指针:
概念:他是一个指针,该指针指向的是一个数组的类型
语法:
int (*ptr) [5] ; // 一个指针,该指针指向拥有5个整型数据的数组 【整型数组指针】
char (*ptr) [5] ; // 一个指向用于5个字符型的数组 【字符数组指针、 字符串数组指针】
#include <stdio.h>
int main(int argc, char const *argv[])
{
int arr [5] = {1,20,3,4,5};
int (*ptr) [5] ;
ptr = &arr ;
int * p = arr ;
// p == arr ;
// ptr = &arr ;
// **ptr = **&arr = *arr = 1
printf("**ptr:%d\n", **ptr); // 1,ptr解引用得到arr,arr为数组首元素地址,解引用得到数组首元素,即1
printf("**ptr+1:%d\n", **ptr+1); // 2,同上,1+1=2
// *(*ptr+1) == *(*&arr+1) = *(arr+1)
printf("*(*ptr+1):%d\n", *(*ptr+1)); // 20,ptr解引用得到数组arr,arr为数组首元素地址,+1加一个数组首元素地址大小,解引用得到数组第二个元素
printf("*(*(ptr+0)+1):%d\n", *(*(ptr+0)+1)); // 20,ptr解引用得到arr,arr为数组首元素地址,+1加一个数组首元素地址大小,解引用得到数组第二个元素
printf("ptr[0][1]:%d\n", ptr[0][1] ); // 20,相当于*(*(ptr+0)+1),同上
// 【拓展】 预习函数的形参中出现数组
// 一下两种写法是等价的,第一种写法是用于强调(告诉使用者)
// 函数pipe 需要的地址必须有两个以上整型的合法内存空间
// int pipe(int pipefd[2]);
// int pipe(int * pipefd);
char msg1[] = "Hello";
char msg2[] = "World";
char msg3[] = "WangDaNiang";
char msg4[] = "ShiDaSao";
char msg5[] = "!";
char * arr1[5] = { msg1, msg2, msg3 ,msg4 , msg5};
char *(* ptr1) [5] = &arr1;
// 操作练习通过ptr1来实现一下操作:
// 1. 数组以上所有的字符串 "Hello" , "World" , "!" , "!" , "!"
for (int i = 0; i < 5 ; i++)
{
// ptr1 = &arr1
//(*ptr1) = arr1
printf("arr1[%d]:%s\n" , i , (*ptr1)[i] );
//&arr1为整个数组的地址,ptr解引用得到数组arr1,arr1为数组首元素地址,arr1[i]得到数组的元素
}
// 2.1 尝试修改某一个字符
// arr1[2][5] -> (*ptr1)[2][5]
// ptr1 = &arr1
(*ptr1)[2][5] = 'A';
//&arr1为整个数组的地址,ptr解引用得到数组arr1,arr1[2][5]得到数组第三个元素的第六个元素
printf("arr1[2]:%s\n" , arr1[2] );
// 2.2 尝试把所有的小写字符转换为大写
for (int i = 0; i < 5 ; i++)
{
for (int j = 0; j < 32 ; j++)
{
if ((*ptr1)[i][j] != '\0' &&
(*ptr1)[i][j] >= 'a' &&
(*ptr1)[i][j] <= 'z' )
{
(*ptr1)[i][j] -= 32 ;
}
}
}
for (int i = 0; i < 5 ; i++)
{
// ptr1 = &arr1
//(*ptr1) = arr1
printf("arr1[%d]:%s\n" , i , (*ptr1)[i] );
//&arr1为整个数组的地址,解引用得到数组arr1,然后arr1[i]访问数组每个元素,打印出改变大小写后的每个字符串
}
// char * p1 = &"Hello" ;
return 0;
}
指针数组指针:
概念:他是一个指针,该指针所指向的内存是一个数组的类型,该数组存储的指针类型的元素。
语法:
int * (*ptr) [5] ;
数组指针指针:
概念:他是一个指针,该指针指向的是另外一个指针,该指针指向的是数组的地址。
语法:
int (*(*ptr)) [5] ;
-
- 为什么数组名不可以直接赋值
int arr[3];
arr = 123 ; // 该操作在试图改变arr的地址 , 有明显的逻辑问题(语法错误)
arr[0] = 123 ;
*(arr+1) = 456 ;
-
- 数组名为什么不能++
int arr [3];
arr ++ ; // arr++ -》 arr = arr + 1; 加完之后等式两边不等,左