初级指针
本篇主要介绍:指针和变量的关系
、指针类型、指针的运算符
、空指针和野指针、指针和数组
、指针和字符串
、const 和指针、以及gdb 调试段错误
。
基础概念
指针是一种特殊的变量。存放地址的变量就是指针。
int num = 1;
会申请4个字节的内存来存放数字1,每次访问 num 就是访问这4个字节。
访问内存中的这4个字节,不仅可以通过名称(例如 num),还可以通过地址
。
Tip:&
不仅是位运算符,还是取地址
操作符。例如 int* ptr = #
,就是取变量 num 的地址并将其保存到指针变量 ptr 中
请看示例:
#include <stdio.h>
int main() {
int num = 10;
// num 的地址:0x7fff4dbf01d8
printf("num 的地址:%p\n", &num);
// num 的地址加1 :0x7fff4dbf01dc。
printf("num 的地址加1 :%p\n", &num + 1);
// j 存放连续内存的第一个字节地址
int *j = #
// 10。通过地址访问
printf("%d", *j);
return 0;
}
&num
和 &num + 1
相差4个字节,说明 &num 表示整数。
普通变量存放值,而指针用于存放地址。
通过 int *j = &num
将变量num的首地址给到指针 j(j的类型是 int *
),最后通过地址(*j
) 访问整数1。
int *j
是一个int类型的指针,还有 char、float等指针类型。指针类型必须匹配,比如将 j 的指针类型换成 char,则会警告。就像这样:
- int *j = #
+ char *j = #
运行:
/workspace/CProject-test/main.c:12:11: warning: incompatible pointer types initializing 'char *' with an expression of type 'int *' [-Wincompatible-pointer-types]
char *j = #
^ ~~~~
1 warning generated.
num 的地址:0x7ffddcfe5328
num 的地址加1 :0x7ffddcfe532c
10
Tip: 指针 j 也有地址,也就是指针的指针。现在不研究
练习
题目
:请问输出什么?
#include <stdio.h>
int main() {
int num = 10;
int *p = #
printf("用指针访问数据 num :%d\n", *p);
*p = 11;
printf("用过指针修改 num 数据:%d\n", num);
return 0;
}
提示:数据可以通过变量访问,也能使用地址(指针)访问。就像通知同学去嵌入式实验室上课,或者是 303 上课。其中*p = 11;
等价于 num = 11;
输出:
用指针访问数据 num :10
用过指针修改 num 数据:11
星号的作用
指针 *
有两个主要作用(根据*
前面有无类型做区分):
- 指针类型声明
- 取值(又称解引用操作符)。例如,*ptr 表示获取指针变量 ptr 所指向内存地址上的值。
请看示例:
#include <stdio.h>
int main() {
int num = 10;
// 指针类型声明
int *p = #
// 取值
printf("%d\n", *p); // 10
// 取值
*p = 11;
printf("%d\n", num); // 11
return 0;
}
指针类型
所占字节
在32位系统上,指针通常占用4个字节;而在64位系统上,指针通常占用8个字节。请看示例:
#include <stdio.h>
int main() {
printf("char类型指针所占字节数为:%zu\n", sizeof(char*));
printf("short类型指针所占字节数为:%zu\n", sizeof(short*));
printf("int类型指针所占字节数为:%zu\n", sizeof(int*));
printf("long类型指针所占字节数为:%zu\n", sizeof(long*));
printf("float类型指针所占字节数为:%zu\n", sizeof(float*));
printf("double类型指针所占字节数为:%zu\n", sizeof(double*));
printf("long long类型指针所占字节数为:%zu\n", sizeof(long long*));
return 0;
}
输出:
char类型指针所占字节数为:8
short类型指针所占字节数为:8
int类型指针所占字节数为:8
long类型指针所占字节数为:8
float类型指针所占字节数为:8
double类型指针所占字节数为:8
long long类型指针所占字节数为:8
练习
题目
:请问整数类型的指针和字符类型的指针加1分别是几个字节?
#include <stdio.h>
int main() {
int num = 10;
printf("num 的地址:%p\n", &num);
printf("num 的地址加1 :%p\n", &num + 1);
char ch = 'a';
printf("ch 的地址:%p\n", &ch);
printf("ch 的地址加1 :%p\n", &ch + 1);
return 0;
}
输出:
num 的地址:0x7fffe8244288
num 的地址加1 :0x7fffe824428c
ch 的地址:0x7fffe8244287
ch 的地址加1 :0x7fffe8244288
答案
:int *
加1是4个字节;char *
加1是1个字节。&num 和 &ch 分别代表该变量的全部字节。
指针交换数据
比如这段代码是不能实现 a、b 两数交换。请看示例:
#include <stdio.h>
void swap(x, y){
int tmp = x;
x = y;
y = tmp;
}
int main() {
int a = 1;
int b = 2;
swap(a, b);
printf("a:%d\n", a);
printf("b:%d\n", b);
return 0;
}
a:1
b:2
分析:调用 swap(a, b)
这里是一个值传递,找到函数入口地址,对参数 x、y 申请空间和赋值,通过 tmp 变量完成了 x和y的交换,最后回收局部变量 x、y和tmp,释放空间。而 a,b数据没有变化。
可以通过指针来实现两数的交换。请看示例:
#include &