文章目录
一、字符指针
- 一般的我们字符指针如下:将c的地址取出来放到p中去,指针p的类型是char*。
#include <stdio.h>
int main()
{
char c = 'w';
char* p = &c;
printf("%c\n", *p);
return 0;
}
- 还有另外一种,如下:将字符串首元素的地址存在p中,p的地址仍然是char*类型,当我们需要打印该字符串时就提供该字符串首元素的地址,然后就会打印出整个字符串。
#include <stdio.h>
int main()
{
char* p = "hello";
printf("%s\n", p);
return 0;
}
注意,上述代码并不是将整个字符串“hello"放在了p中。
看下面一段代码。
#include <stdio.h>
int main()
{
char str1[] = "hello";
char str2[] = "hello";
char* str3 = "hello";
char* str4 = "hello";
if (str1 == str2)
printf("str1 == str2\n");
else
printf("str1 != str2\n");
if (str3 == str4)
printf("str3 == str4\n");
else
printf("str3 != str4\n");
return 0;
}
我们创建了两个数组,因此会开辟两处不同的空间,数组名是首元素的地址,故str1 != str2,即使看上去它们两个存放了同样的内容;
接着对于str3、str4,它们两个存放了同一个字符串常量的首元素地址,故str3 == str4。
总结:C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,它们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。
二、指针数组
关于指针数组详见指针(1),下面简单解释几个例子:
int* arr1[10]; //在数组arr1中存放了10个int*类型的一级指针
char *arr2[4]; //在数组arr2中存放了4个char*类型的一级指针
char **arr3[5];//在数组arr3中存放了5个char**类型的二级指针
三、数组指针
1. 数组指针的创建与意义
简单来说数组指针就是存放数组的地址的指针变量,它是一个指针。
它所指向的是整个数组。
下面就是一个创建数组指针的例子:
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;
return 0;
}
int(*p)[10] = &arr;关于这个的解释如下:将数组arr的地址取出存放在p中,这时的p就是一个数组指针,它所指向的是整个数组,p的类型是int ( * )[10]。
下面我们就看看数组指针到底与数组名有什么不同:
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;
printf("%p\n", arr);
printf("%p\n", arr + 1);
printf("%p\n", p);
printf("%p\n", p + 1);
return 0;
}
结果如下
我们从第一个和第三个结果可以看出p与arr所储存的地址是一样的,都是数组首元素的地址,但当我们仔细分别观察第1,2个结果与第3,4个结果会发现,,当我们给arr+1后会跳过一个整型的内容,但给p+1时发现跳过了10个整型的内容,刚好就是数组arr的内容,这就让我们更加确信,虽然数组指针p与arr都储存了数组中首元素的地址,但数组指针p指向的是整个数组的内容,它们的意义截然不同。
2. 数组指针的使用
#include <stdio.h>
void Print(int(*p)[4], int r, int c)
{
int i = 0;
for (i = 0; i < r; i++)//控制访问每个一维数组
{
int j = 0;
for (j = 0; j < c; j++)//控制访问每一个一维数组中的每一个元素
{
printf("%d ", (*(p+i))[j]);
}
printf("\n");
}
}
int main()
{
int arr[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
Print(arr, 3, 4);
return 0;
}
在这段代码中,我们创建了一个二维数组arr,我们将arr当作一个数组指针传给了Print函数,当然了我们也是以一个类型为int ( * )[4]的数组指针p接收的,我们知道可以将二维数组看成由多个一维数组构成,每一个一维数组都是二维数组的一个元素,那么我们就可以利用循环来访问每一个一位数组(具体方法就是给数组指针p+1来跳过当前一维数组,访问下一个一维数组,其实就是实现了printf("%d ", (*(p+i))[j])),然后再借助循环来打印一维数组中的每个元素,这样其实就是利用数组指针打印了二维数组的每一个元素。
4.数组参数、指针参数
在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?
1.一维数组传参
比如下面的代码,如何设计形参接收呢?
int main()
{
int arr[10] = {0};
int *arr2[20] = {0};
test(arr);
test2(arr2);
}
- void test ( int arr[ ] ) : 对于通过test函数传了一维数组名,也就是一个数组,当然可以用数组接收,并且可以不指定大小。
- void test ( int arr[10] ):这与 1. 相同,只不过我了与数组的大小,并且大小与创建的数组一致。
- void test ( int *arr ):我们知道数组名是数组首元素的地址,并且这个地址指向的元素类型是int类型,那么我们就可以创建一个int * 类型的指针来接收。
- void test2 ( int *arr[20] ):对于int *arr2[20] = {0}数组传参,同样的道理我们可以用一个一致的数组来接收。
- void test2(int **arr):对于数组int *arr2[20] = {0},我们知道这是一个指针数组,当我们传过去数组名时我们就可以用一个二级指针来接收,原因是arr2表示数组中首元素的地址,而该数组是存放指针的数组,那么接收指针的地址就要用二级指针来接收。
2.二维数组传参
int main()
{
int arr[3][5] = {0};
test(arr);
}
标签:arr,int,void,参数,数组,test,指针 From: https://blog.csdn.net/shadoubuhuijiji/article/details/144743913
- void test ( int arr [3][5] ):这是非常标准的接收,传过来数组,就用一致类型的数组来接收。
- void test ( int arr [ ][ ] ):这是标准的错误,我们在用数组接收实参时二维数组不能省略列数。
例如,我们可以这样接收void test ( int arr [ ][5] )。
总结:二维数组传参,函数形参的设计只能省略第一个 [ ] 的数字。- 这样void test ( int arr )不能接收,因为二维数组的数组名代表二维数组中第一行的地址,也就是一个义务为数组的地址,表示一个数组指针,当然不能用一级指针来接收。
这样void test ( int arr [5] )不能接收,形参部分是一个指针数组。
这样void test ( int **arr )更不能接收,二维数组数组名代表一个一维数组的地址,是一个数组的的地址,根本上它是一个一级指针,当然不能用二级指针来接收了。- 我们可以用一个数组指针来接收:void test ( int (*arr)[5] )。