引言:
1.我们都知道指针是存放地址,那指针变量就是存放地址的变量,而指针变量的类型取决与这块地址里所放的数据类型。
2.指针的大小是固定的4/8个字节(取决于32位平台/64位平台)也就是X86/X64。
3.指针进行加减运算时,指针的类型决定所走的步长,指针解引用操作时的权限。
1.字符指针
我觉得需要注意的一点,就是下面这个例子。
这里的char* p="abcdefj" p的指向是字符a的地址,“abcdefj”是常量字符串不能修改。
例子:
#include<stdio.h>
int main()
{
char arr1[]="hello world";
char arr2[]="hello world";
char* p1="hello world";
char* p2="hello world";
if(arr1==arr2)
{
printf("arr1 and arr2 are same");
}
else
{
printf("arr1 and arr2 are not same");
}
if(p1==p2)
{
printf("arr1 and arr2 are same");
}
else
{
printf("arr1 and arr2 are not same");
}
return 0;
}
这里的p1和p2指向的是一个同一个常量字符串。c/c++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。
2.指针数组
它是存放指针类型的数组。
定义类型: void * arr[10]
3.数组指针
它是指针,指针变量里存放的是数组的地址。
定义类型:void ( *p) [10]
这里我们要讲一下,数组名和&数组名的区别。
数组名表示数组首元素的地址,有两个例外:
1.sizeof(数组名) :这里的数组名表示的是整个数组
2.&数组名:也表示整个数组,他的地址虽然与数组首元素地址一样,但是与数组名其意义不一样。
4.数组传参,指针传参。
1.一维数组传参
void test(int arr[])//ok?
{}
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;
}
上面代码的传参是否合理能,可以去验证一下,不会的可以私信我哦!
总结:一维数组
形参可以是指针,也可以是数组,当形参是指针时,要注意传参的类型。
2.二维数组传参
void test(int arr[3][5])//ok?
{}
void test(int arr[][])//ok?
{}
void test(int arr[][5])//ok?
{}
void test(int* arr)//ok?
{}
void test(int* arr[5])//ok?
{}
void test(int (*arr)[5])//ok?
{}
void test(int** arr)//ok?
{}
int main()
{
int arr[3][5] = { 0 };
test(arr);
return 0;
}
同上哦,想知道答案?
总结:二维数组
参数可以是指针,也可以是数组。
如果是数组行可以省,但列不能省。
如果是指针,传过去的是第一行的地址,形参就应该是数组指针。
3.一级指针传参,二级指针传参
只需要注意,当函数的参数部分为一级指针和二级指针时,函数能接受什么参数?
5.函数指针
顾名思义,是存放函数地址的指针。
这里也有一点,函数名和&函数名的意义相同的。(有待反驳,是否联想到数组,是否会出现和数组名一样的情况)
定义形式:void (*p)(),最后一个括号里面是函数的参数,而void 是函数的返回值。
这里有两个有意思的代码,可以深究一下,理解万岁。
(* ( void(*)() ) 0)()
void (*signal( int,void(*)(int) ) )(int)
小伙伴们,思考思考把,答案即在作者手中,或者全网之中。