变量
通过变量名访问变量,称为直接访问;
通过指针方式访问,称为间接访问;
变量名是为了方便程序员使用而定义的,
内存存放数据的真相
指针
指针就是地址的意思
指针变量
指针变量是用来的存放地址的变量。普通的变量中存放的是数据,指针变量中存放的是地址;
指针变量的类型:存放的地址指向的数据类型;
假设定义两个指针变量pa和pf,指针变量在内存中,占4个字节。
其中“11000”:是指针变量pf的存放的地址,在这个内容中存放的"10005"是整型变量的地址,这个整型变量存放的是“123”。
定义指针变量
类型名 *指针变量名
char *pa;//定义一个指向字符型的指针变量
int *pb;//定义一个指向整型的指针变量
取地址运算符和取值运算符
获取某个变量的地址,使用取地址运算符(&)
char *pa = &a;
char *pb = &f;
访问指针变量指向的数据,使用取值运算符(*)
printf("%c,%d\n",*pa,*pb);
注意:在定义指针变量和取值时使用的是同一个符号,这是数据符号的重用,在不同的场合具有不同的作用;
在定义的时候,表示定义一个指针变量;
在其他地方,表示取指针变量指向的那个变量的值;通过指针方式访问,称为间接访问,所以,“*”也成为间接运算符;
简单的例子回顾
#include<stdio.h>
int main()
{
char a = 'F';
int f = 123;
char *pa = &a;//定义指针变量
int *pb = &f;
printf("a = %c\n", *pa);
printf("f = %d\n", *pb);
//打印变量地址
printf("the addr of a = %p\n", pa);//这是变量a 的地址
printf("the addr of f = %p\n", pb);
printf("the addr of pa = %p\n", &pa);//这是指针变量的地址
return 0;
}
运行结果:
a = F
f = 123
the addr of a = 000000791A1BFC54
the addr of f = 000000791A1BFC74
the addr of pa = 000000791A1BFC98
请按任意键继续. . .
避免访问未初始化的指针
如下
#include <stdio.h>
int main()
{
int *a;//地址随机分配
*a = 123;
return 0;
}
报错!!!
小甲鱼的《带你学C带你飞课后题》
0. 通常程序猿口中的“指针”,指的是什么东西?
答:指针就是内存的地址。
1. 指针变量只能存放地址吗?
答:是的,指针变量里面只能存储地址,不能存放其他内容。
2. 请问 int * a, b, c; 定义了多少个指针变量?
答:一个。只有a是指针变量,其他的都是普通的变量。
3. 请问 int *(a, b, c); 定义了多少个指针变量?
答:这句话是有语法错误,定义三个指针变量应该: int *a,*b,*c;
4. 在内存中捕获到一组 32 位数据如下:
0110 0111 0110 1100 0110 1111 0110 0010
请问它的值可能是(多选,可借助计算工具):
A. 1 个 32 位整数:1735159650
B. 2 个 16 位整数:26476 和 28514
C. 4 个字符:glob
D. 浮点数:1.116533 * 10^24
答:都正确。
内存中存放值不是0就是1,如何解释,需要看定义。如果你看不到定义(你在逆向破解一个程序),那么为了判断值的类型,你必须观察程序中这个值的使用方式(如果使用整型算术指令,这个值就被解释为整数;如果使用浮点型指令,它就是浮点数)。
5. 你觉得将取址运算符(&)作用于一个常数,然后试图打印该常数在内存中的地址,这样做可取吗?
答:不可以,因为取址操作符(&)的作用对象应该是一个左值,而常数是右值。简单区分,左值是必须可以改变的。
6 请问下边代码是否可以成功执行呢?为什么?
#include <stdio.h>
int main()
{
int a, b;
b = 110;
a = &b;
printf("%d\n", *a);
return 0;
}
这种做法编译器并不会认可,编译不通过,它会毫不犹豫给你直接报错!
7. 请问为什么每次执行下边代码都会得到不同的结果?
#include <stdio.h>
int main()
{
int *a;
printf("%p\n", a);
return 0;
}
答:这里我们声明了一个指针变量 a,但并未对它进行初始化,这是非常危险的行为!因为我们没办法预测这个指针变量的值会被初始化为什么,它只是恰好内存中存在的“随机值”
8. 请问下边代码执行后,打印机的结果是什么?另外,*b 是左值(l-value)还是右值(r-value)?
#include <stdio.h>
int main()
{
int a = 110;
int *b = &a;
*b = *b - 10;
printf("a = %d\n", a);
return 0;
}
答:打印结果:a = 100
第一个问题:定义指针变量 b 的时候,存放的是变量 a 的地址。在此之后,*b 即对变量 a 的间接访问(通过地址访问 a 变量)。所以 *b = *b - 10; 相当于 a = a - 10; 也就是说,通过指针对一个变量间接访问,你可以理解为把它作为那个变量本身使唤(即 *b == a)
第二个问题:指针变量 b 既是左值,也是右值。看 *b = *b - 10; 这个语句,赋值号右边,*b 间接访问变量 a 的值,因为用的是它的值,所以是右值;赋值号左边,*b 用于定位变量 a 的存储位置,然后将右边表达式的值存放进去,所以此时为左值
★finished by songpl, 2018.12.27