1、字符指针
const char* p = "abcdefg";//"abcdefg"是一个常量字符串。把首元素a的地址赋给p。
//常量字符串不允许被改变,可以加const修饰
//容易以为是把字符串abcdefg放到字符指针p里了,但本质是把字符串abcdefg首字符的地址放到p中。
printf("%c\n", *p); //a
printf("%s\n", p); //abcdefg
下面代码存在问题
//*p = 'W';//常量字符串不能被改变,代码会崩溃
//printf("%s\n", p);
面试题,输出结果是什么?
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char* str3 = "hello bit.";
const char* str4 = "hello bit.";//常量字符串,理论上不能被修改,只能拿去用。加const修饰。
str3和str4的内容一样,常量字符串为了节省内存空间,存一份就可以了。str3和str4都指向同一块空间的起始位置。
数组名是首元素地址,首元素地址在不同的空间,所以str1 != str2
if (str1 == str2)
{
printf("str1 and str2 are same\n");
}
else
{
printf("str1 and str2 are not same\n");
}
//str3和str4都指向同一块空间的起始位置。
if (str3 == str4)
{
printf("str3 and str4 are same\n");
}
else
{
printf("str3 and str4 are not same\n");
}
分析:这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。数组其实是放在内存的栈上,常量字符串是放在内存的只读数据区。所以str1和str2不同,str3和str4不同。
2、指针数组
指针数组是数组,用来存放指针的数组。
int arr[10] = { 0 }; //整型数组
char ch[5] = { 0 }; //字符数组
int* parr[4]; //存放整形指针的数组 - 指针数组
char* pch[4]; //存放字符指针的数组 - 指针数组
char **arr3[5]; //二级字符指针的数组
例:
int a = 10;
int b = 20;
int c = 30;
int d = 40;
int* pa[4] = { &a,&b,&c,&d };
int sz = sizeof(pa) / sizeof(pa[0]);
//printf("sz = %d\n", sz);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%p\n", pa[i]); //指针数组存放的是整形指针,打印的是地址
}
for (i = 0; i < sz; i++)
{
printf("%d ", *(pa[i]));//整形指针解引用,拿到地址中的内容
}
例:
数组名是首元素地址
int arr1[] = { 1,2,3,4,5 };//整型数组
int arr2[] = { 2,3,4,5,6 };//整型数组
int arr3[] = { 3,4,5,6,7 };//整型数组
//通过存放在指针数组中的数组名,打印数组中的元素
int* parr[] = { arr1,arr2,arr3 };//存放整形指针的指针数组,里面的数组名是首元素地址。
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", *(parr[i] + j));
//指针 +- 整数。指针的类型决定了指针向前或者向后走一步有多大(距离)。
}
printf("\n");
}
3、数组指针
数组指针是指针还是数组?答案是指针。
int* pint = NULL; //整形指针:能够指向整型的指针,可以存放整型的地址。
char* pc = NULL; //字符指针:指向字符的指针,可以存放字符的地址。
float* pf = NULL; //浮点型指针:能够指向浮点型数据的指针,可以存放浮点型的地址。
数组指针应该是:能够指向数组的指针,可以存放数组的地址。
写法等价,arr[i] == *(p + i) == *(arr + i) == p[i]
int(*p)[10] = &arr;
//*首先与p结合,p就是数组指针。*表示p是指针,[ ]表示指针指向的是数组,每个元素是int类型
//数组指针是能够指向数组的指针,可以存放数组的地址。
那数组指针是怎么使用的呢?
既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。
数组指针至少用在二维数组以上才方便一些。
4、函数指针
数组指针 - 是指向数组的指针 - 存放数组的地址
函数指针 - 是指向函数的指针 - 存放函数地址的指针
&函数名和函数名都是函数的地址
例
int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
void Print(char* str)
{
printf("%s\n", str);
}
int main()
{
//数组指针 - 是指向数组的指针 - 存放数组的地址
//函数指针 - 是指向函数的指针 - 存放函数地址的指针
//int a = 10;
//int b = 20;
//printf("%d\n", Add(a, b));
//&函数名和函数名都是函数的地址
//printf("%p\n", &Add);//打印的是Add函数的地址
//printf("%p\n", Add);//打印的是Add函数的地址
int (*pa)(int, int) = Add;
printf("%d\n", (*pa)(2, 3));
printf("%d\n", Add(2, 3));//函数名是函数的地址
printf("%d\n", pa(2, 3));//pa是函数指针,存放的是函数地址,函数名也是函数的地址,所以调用函数的时候可以不解引用