#include <stdio.h>
int main() {
int a = 10;
printf("a = %d\n", a);
int* a_p;
//a_p = 0; //相当于a_p是空指针,与a_p = NULL含义相同。
//a_p = a; //不能将 "int" 类型的值分配到 "int *" 类型的实体。
//int* temp = (int*)a; //将a强转为指针后,该指针所指向的地址是未定义的。
//因为a本身是一个整型变量,值是10,而不是一个合法的内存地址。
//因此,这个指针指向的地址是不确定的,可能是一个无效的地址,
//也可能是某个有效的地址,但这个地址不是a本身的地址。
//因此,使用这个指针可能会导致程序崩溃或者产生未定义的行为。
a_p = &a; //正确的赋值,"&" 相当于某种意义上的 “类型转换”,即“取地址”。
printf("a = %d\n", *a_p); //正确的输出,"*" 也相当于某种意义上的“类型转换” 。
// "*" 运算符是对指针变量 p 的 “解引用”。
//鼠标停到 "a_p" 上方,可以看到 "a_p" 的数据类型是 "int *",
//对一个 "int *" 类型的数据再使用一次 "*" 运算符,就回到了 "int" 类型。
//综上,"*" 运算符有两种含义:定义指针、解引用,需要根据上下文来判断。
//a_p = NULL; //需要注意的是,当指针变量没有指向任何有效的内存地址时,
//printf("a = %d\n", *a_p); //对其进行解引用操作可能会导致程序崩溃或者产生未定义的行为。
//因此,在解引用指针变量之前,需要确保指针变量已经指向了有效的内存区域。
int b = 20;
int* b_p = &b; //正确的语法,相当于将声明和赋值的两句话合并在一起写了,当前是被允许的。
printf("b = %d\n", *b_p);
//*b_p = &b; //编译报错:不能将 "int *" 类型的值分配到 "int" 类型的实体。
//"int *" 类型的值指的是 "&b","int" 类型的实体指的是 "*b_p"(解引用)。
int c = (int)b_p; //如果把一个指针强制转换为 "int" 类型,输出结果是什么呢?
printf("c = %d\n", c); //强制转换后,输出的结果是该指针所指向内存地址的整数表示。
//因为在32位系统中,一个指针占用4个字节,而一个 "int" 类型也占用4个字节,
//因此可以将指针强制转换为 "int",以便将其作为整数进行处理。
//但是,这个整数值并不具有实际意义,它只是一个内存地址的整数表示。
printf("b_p = %p\n", b_p); //如果要将一个指针转换为实际的内存地址,可以使用 %p 格式化符号进行输出。
//这个结果是十六进制的。
printf("b = %d\n", *&*b_p); //如果这样套娃,输出结果会是什么呢?答案其实已经告诉你了。
printf("%d\n", 10**&*b_p); //没有忘记 "*" 运算符还可以是乘号吧?建议加个括号。
//当然,不会有人这么写代码的。除非他真的很闲,而且以给别人制造麻烦为乐。
return 0;
}
刚刚上完指针的第一节课,稍微梳理了一下,记点笔记。
想起Java中没有显式的指针概念,但动不动就给我爆一个NullPointerException,这就是被指针支配的恐惧吗?