int main()
{
char ch = 'w';
char *pc = &ch;
*pc = 'w';
return 0;
}
还有一种使用方法
int main()
{
const char* pstr = "hello bit.";//这⾥是把⼀个字符串放到pstr指针变量⾥了吗?
printf("%s\n", pstr);
return 0;
}
上面的代码里const char* pstr ="hello bit"并不是把字符串hello bit存入指针pstr里,而是把hello bit的首字符地址存入指针里,就是h的地址,详细如下:
《剑指offer》里面有一道和字符转有关的题目我们来看看:
#include <stdio.h>
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;
}
这里会有人有疑问了,为什么会得到这个结果呢?我们首先需要知道一个知识,c/c++会把常量存储到常量存储区中,所以指针str3和str4指向的是同一个常量字符串,所以str3==str4。str1和str2是两个数组,内存会分配地址给他们,所以str1和str2里的hello bit地址并不相同。
2.数组指针变量:
之前我们说过了指针数组,指针数组就是把n个指针存入数组里,那么数组指针变量是数组还是指针呢?答案是肯定的,就像字符指针变量是存放字符变量的地址,能够指向字符数据的指针,整形指针变量是存放整形变量的地址,能够指向整形数据的指针,数组指针变量当然就是存放数组的地址,能够指向数组的指针。
int * ptr=arr[10]; int (*p)[10]; 思考一下ptr和p分别是什么?
int (*p)[10];
上面代码里的p就是数组指针变量,p先和*结合,意思p是指针变量,然后p指向的是数组大小是10的整形数组。这里的()是必要的,因为[ ]优先级比*高,如果不打括号,p会先和[ ]结合,这个p就变成了数组名p[10]了。
那么这里我们如何把数组的地址存入指针里呢?用到的就是之前比较过的&arr。 int (*p)[10]=&arr;这里调试可以看出来&arr和指针变量p的类型都是int [10]*。
3.二维数组传参的本质:
过去我们二维数组传参都是void test(int a[3][5], int r, int c),这里的实参是数组,形参也是数组,那么还有别的表达方式吗。要知道还有什么表达方式我们需要深度理解一下二维数组,我们可以把二维数组看成一维数组里存放了几个一维数组int arr[3][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}},并且二维数组首元素地址就是第一行一维数组的地址,根据上面的解释,一维数组元素类型是int [5],那么第一行一维数组地址的类型就是int (*)[5],所以本质上二维数组传参也是传递了地址,所以我们也可以用数组指针表示。
#include <stdio.h>
void test(int (*p)[5], int r, int c) {
int i = 0;
int j = 0;
for(i=0; i<r; i++)
{
for(j=0; j<c; j++)
{
printf("%d ", *(*(p+i)+j));
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {{1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7}};
test(arr, 3, 5);
return 0;
}
4.函数指针变量:
听名识曲,顾名思义,函数指针变量是存放函数地址的指针变量,可以调用函数。那么函数有地址吗?可以看出来函数是有地址的,并且函数名就是函数的地址,可以直接函数名也可以&函数名。
函数指针变量创建如下:
void test()
{
printf("hehe\n");
}
void (*pf1)() = &test;
void (*pf2)()= test;
int Add(int x, int y)
{
return x+y;
}
int(*pf3)(int, int) = Add;
int(*pf3)(int x, int y) = &Add;
使用函数指针调用函数
typedef关键字:typedef是可以给类型重命名的
typedef unsigned int uint;
//将unsigned int 重命名为uint
typedef int* ptr_t;
//定义指针类型
typedef int(*parr_t)[5];
//定义数组指针类型
typedef void(*pfun_t)(int);
//定义函数指针类型
这里需要特殊观察的是数组指针和函数指针,新的类型名需要在*的右边。
5.函数指针数组:
经过我们一层层的套娃,也是来到了函数指针类型,函数指针类型顾名又思义是数组,数组里存放的是函数的指针(地址)。那么函数指针的数组该如何定义呢?给三种可能结果: