指针变量: 定义一个变量,而变量的值是另一个变量的地址。这个变量就叫指针变量,可以通过运算符*获取这个指针变量存储的地址所指向的内存空间。指针变量在64位系统中占8个字节。而long long也是占8个字节,但是使用long long来保存地址和使用指针变量保存地址是有区别的。
变量的地址: 变量存储在内存空间中的一个位置,数组的地址就是数组第一个元素的地址。数组的名字即为数组的地址指针,也可以使用运算符&获取任何变量的地址。
- 一段简单代码理解指针和数组之间的关系。
#include <stdio.h>
int main() {
int a[][3] = {1, 3, 5, 7, 9, 11};
int *b = &a[0][0];//将数组第一个元素的地址赋值给指针变量
long long c = a;//数组的起始地址,也就是第一个元素的地址赋值给long long整型
long long d = a[1];//二维数组可以看成元素类型是一维数组的一维数组,这里是第二个一维数组的首地址
long long *e = &a[1][0];//指针变量指向二维数组中第二个一维数组的首地址
long long f = &a[1][0];//long long类型存储数组的地址
printf("%p\n", b);//值和c相同
printf("%p\n", c);
printf("%p\n", d);//值和ef相同
printf("%p\n", e);
printf("%p\n", f);
printf("%d\n", *b);//1 数组第一个元素的值
printf("%d\n", *(b + 1));//3 数组第二个元素的值
// printf("%d\n", *c);//这里是错误写法,虽然c存储的也是某个变量的地址,但是并不能使用*取到这个地址指向的空间
int *point = c;//只能定义指针变量先赋值,再使用*获取对应空间的值
printf("%d\n", *point);//1
printf("%d\n", *(point + 1));//3 数组第二个元素的值,指针变量直接自增一或自减一就可以到达数组下一个或上一个元素的地址
int *point2 = c + sizeof(int);//而long long需要加一个数组元素类型的长度,才能到达下一个元素的地址
printf("%d\n", *point2);//3 数组第二个元素的值
printf("point2:%d\n", *(point2 + 1));//3 数组第三个元素的值
point = d;
printf("%d\n", *point);//7
printf("%d\n", *e);//7
point = f;
printf("%d\n", *point);//7
return 0;
}
- 指针与字符串的关系
定义字符串有两种方式,一种是字符数组,一种是字符串指针。
#include <stdio.h>
#include "string.h"
int main() {
char str1[] = "abc";
printf("str1 is: %s\n", str1);//abc
for (int i = 0; i < strlen(str1); i++) {
printf("%c\n", *(str1 + i));
}
char *str2 = "def";
printf("str2 is: %s\n", str2);//def
for (int i = 0; i < strlen(str2); i++) {
printf("%c\n", *(str2 + i));
}
*(str1 + 1) = 'g';//修改后为agc
printf("str1 is: %s\n", str1);//agc
// *(str2 + 1) = 'g';//不能这么写,因为字符指针保存的是字符串常量地址,不可以修改
scanf("%s", str1);
printf("str1 is: %s\n", str1);
// scanf("%s", str2);//同样不能这么写
}
- 指向函数指针
函数在内存中页要占据存储空间,也有一个起始地址,可以利用一个指针指向一个函数。函数名就代表函数的地址。
指针函数的定义:
返回值类型(*指针变量名)(形参1,形参2,...);
示例:
#include <stdio.h>
int sum(int a, int b);
int main() {
int (*p)(int, int);
p = sum;
printf("%p", p);
}
int sum(int a, int b) {
return a + b;
}