int a = 5;
printf("a的地址为:%p, a的值为:%d\n",&a, a);
其中&a指的是变量a在内存中的地址,a是变量的值。&是取值符号。
int a = 5;
int *p; // p 是未初始化的指针,指向随机内存地址
*p = a; // 试图将 a 的值写入 p 指向的随机地址(危险!)
分析这段错误的代码
不要以为声明指针后就可以直接使用,必须需要先让指针指向有效的内存区域。
比如用p = &a; 或者动态分配内存。
永远不要对未初始化的指针解引用(即 *p
)。
指针必须指向以下之一才能安全使用:
p = &a
)。p = malloc(...)
)。关键问题:指针 p
未初始化,它存储的是一个随机的内存地址(垃圾值)。直接通过 *p = a
向这个随机地址写入数据,可能导致以下后果:
p
指向合法内存地址int a = 5;
int *p = &a; // p 指向变量 a 的地址
*p = 10; // 合法操作:修改 a 的值为 10
int a = 5;
int *p = malloc(sizeof(int)); // 动态分配内存
if (p != NULL) {
*p = a; // 合法操作:将 a 的值写入动态分配的内存
free(p); // 使用后释放内存
}
你的代码 | 正确代码 | 区别 |
---|---|---|
int *p; (未初始化) |
int *p = &a; |
指针必须指向有效内存地址 |
*p = a; (危险操作) |
*p = a; (安全操作) |
只有在 p 初始化后合法 |
总结来说,也就是我初始化指针以后,必须要有一个合法的内存地址,不然就是一个随机的,在进行赋值的时候,就会出现上述错误。 |
- 覆盖其他程序或操作系统的重要数据(段错误,程序崩溃)。
- 破坏内存,引发不可预测的行为(未定义行为)。
未初始化的指针类似于一个“野指针”,它指向的内存地址可能是:
受保护的操作系统内存区域(导致程序崩溃)。
其他变量或数据的内存地址(导致数据被意外覆盖)。
无效地址(直接引发段错误)。
假设内存布局如下:
int a = 5; // 地址 0x1000,值 5
int *p; // 存储 p 的地址是 0x2000,值未初始化(假设是 0xABCD)
*p = a
会尝试将 5
写入地址 0xABCD
,而 0xABCD
可能属于其他程序或无效内存,导致崩溃。*p = a
改变这一个未初始化的内存空间的值,这样会导致错误。永远不要对未初始化的指针解引用(即 *p
)。
指针必须指向以下之一才能安全使用:
已存在变量的地址(如 p = &a
)。
动态分配的内存(如 p = malloc(...)
)。
其他合法的内存区域(如数组的首地址)。
建议修正你的代码为:
int a = 5;
int *p = &a; // 先让 p 指向合法地址
*p = a; // 安全操作
int *p;
printf("%p\n", p);
printf("%p\n", &p);
在 C/C++ 语言中,int *p;
的含义是:声明一个指向整型(int
)数据的指针变量 p
。以下是详细解释:
在 C/C++ 中,指针自身的地址(即 &p
)是指针变量 p
在内存中存储的位置。理解这一概念需要区分以下两个关键点:
p
(指针的值):指针变量 p
存储的是它指向的变量的内存地址(例如 int x = 10; p = &x;
,此时 p
的值是 x
的地址)。
&p
(指针自身的地址):指针变量 p
自己作为一个变量,在内存中也有一个存储位置,这个位置的地址就是 &p
。
这里说白了就是内存地址,保存在一个变量中,而我们给这个变量起了一个名字叫指针,我们更多的是通过内存的操作,在某种程度上去操作一些数据。指针本身也需要一个地方去存储,因此就是指针的地址(这个内存空间一般是不需要操作的,因为是用来存储一些地址(指针的值)的,)。
#include
int main() {
int x = 10; // 假设 x 的地址是 0x1000
int *p = &x; // p 存储的是 x 的地址(0x1000)
printf("x 的地址(p 的值):%p\n", (void*)p); // 输出 0x1000
printf("指针 p 自身的地址(&p):%p\n", (void*)&p); // 输出 0x2000(假设 p 的地址是 0x2000)
return 0;
}
int x = 10;
int y = 20;
int *p = &x; // p 指向 x
int **pp = &p; // pp 存储 p 的地址(即 &p)
// 输出变量 x 的地址
printf("变量 x 的地址: %p\n", &x);
// 指针 p 存储的地址,即变量 x 的地址
printf("指针 p 存储的地址,即变量 x 的地址: %p\n", p);
// 输出指针 p 所指向变量的值,即变量 x 的值
printf("指针 p 所指向变量的值: %d\n", *p);
// 输出 存储指针p的地址
printf("存储指针 p 的地址: %p\n", &p);
// 输出指针 pp 存储的地址,即变量 p 的地址
printf("指针 pp 存储的地址,也就是存储指针 p 的地址: %p\n", pp);
// 存储指针 pp 的地址,
printf("存储指针 pp 的地址: %p\n", &pp);
*pp = &y; // 通过 pp 修改 p 的指向,现在 p 指向 y
// 输出变量 y 的地址
printf("变量 y 的地址: %p\n", &y);
// 输出指针 pp 存储的地址,即变量 y 的地址
printf("指针 pp 存储的地址: %p\n", p);
变量 | 内存地址(假设值) | 存储的内容 |
---|---|---|
x |
0x1000 |
10 |
p |
0x2000 |
0x1000 (x 的地址) |
p
的值:0x1000
(指向 x
的地址)。
&p
的值:0x2000
(指针变量 p
自身的内存地址)。
可以通过二级指针(指向指针的指针)修改 p
的指向:
int x = 10;
int y = 20;
int *p = &x; // p 指向 x
int **pp = &p; // pp 存储 p 的地址(即 &p)
*pp = &y; // 通过 pp 修改 p 的指向,现在 p 指向 y
printf("%d\n", *p); // 输出 20
如果需要在函数内部修改指针的指向(如动态内存分配),需要传递指针的地址:
void allocate_memory(int **ptr) {
*ptr = malloc(sizeof(int)); // 通过二级指针修改外部指针的值
}
int main() {
int *p;
allocate_memory(&p); // 传递 p 的地址
*p = 100;
free(p);
return 0;
}
p
和 &p
的类型p
的类型是 int*
(指向整型的指针)。
&p
的类型是 int**
(指向指针的指针)。
即使指针未初始化,&p
仍然是合法的:
int *p; // 未初始化
printf("%p\n", (void*)&p); // 合法,输出 p 自身的地址(如 0x2000)
printf("%p\n", (void*)p); // 危险!p 的值是未定义的(垃圾值)
指针的值(p
):指向某个数据的内存地址。
指针自身的地址(&p
):指针变量本身在内存中的位置。
关键区别:
int x = 10;
int *p = &x;
// p 是 x 的地址(0x1000)
// &p 是 p 自身的地址(0x2000)
理解这一概念是掌握指针操作(如动态内存管理、函数传参)的基础。
int
:表示指针指向的数据类型是整型(int
)。
*
:表示这是一个指针变量。
p
:指针变量的名称。
因此,int *p;
可以理解为:
“p
是一个指针,它能存储某个 int
类型变量的内存地址”。
指针也就是地址,地址也就是指针。
未初始化的指针(如你的代码):
指针 p
的值是未定义的(即“野指针”),它可能指向内存中的任意地址(垃圾值)。
直接操作未初始化的指针(如 *p = 5;
)会导致 未定义行为(程序崩溃、数据损坏等)。
安全用法:始终初始化指针:
int x = 10;
int *p = &x; // p 指向变量 x 的地址
指针 p
的核心作用是 间接访问内存:
通过 p = &x;
可以存储变量 x
的地址。
通过 *p
可以读写 x
的值(即解引用)。
int x = 10;
int *p = &x; // p 存储 x 的地址
printf("x 的值:%d\n", x); // 输出 10
printf("通过 p 访问 x:%d\n", *p); // 输出 10
*p = 20; // 通过 p 修改 x 的值
printf("修改后 x 的值:%d\n", x); // 输出 20
指针的大小与它指向的数据类型无关,只与操作系统位数有关:
32 位系统:指针占 4 字节(如存储地址 0x7fff2a01b3dc
)。
64 位系统:指针占 8 字节(如存储地址 0x7ffee34a9b3c
)。
int* p, q;
中 p
和 q
都是指针?错误!q
是普通 int
变量,只有 p
是指针。
正确写法:
int *p, *q; // p 和 q 都是指针
*
符号是变量名的一部分?*
符号属于类型声明,不是变量名。int* p; // 强调类型是 int*
int *p; // 强调变量 p 是指针(更常见写法)
int *p = malloc(sizeof(int)); // 动态分配内存
*p = 100;
free(p); // 释放内存
void change(int *p) { *p = 20; }
int x = 10;
change(&x); // x 的值变为 20
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr; // p 指向数组首元素
printf("%d\n", p[0]); // 输出 1
int *p = NULL; // 安全初始化
free(p);
p = NULL; // 防止误用已释放的内存
int *p;
声明了一个整型指针变量 p
,它专门用来存储 int
类型变量的内存地址。
指针的核心是 间接访问内存,需初始化后才能安全使用。