【C语言补漏】 指针

变量

通过变量名访问变量,称为直接访问;

通过指针方式访问,称为间接访问;

变量名是为了方便程序员使用而定义的,

内存存放数据的真相

指针

指针就是地址的意思

指针变量

指针变量是用来的存放地址的变量。普通的变量中存放的是数据,指针变量中存放的是地址;

指针变量的类型:存放的地址指向的数据类型;

假设定义两个指针变量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带你飞课后题》

https://fishc.com.cn/forum.php?mod=viewthread&tid=71653&extra=page%3D1%26filter%3Dtypeid%26typeid%3D570

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

猜你喜欢

转载自blog.csdn.net/plSong_CSDN/article/details/85297580