《C语言语法知识》-- 指针

注:本文内容是学习小甲鱼老师讲解后的部分总结。
首先说明内存是如何存放变量的:
变量名的存在只是为了方便程序员使用而设计的,计算机内存中并没有存储变量名,变量名对应的是地址,只有编译器知道。在编译器编译时,它会根据变量名所代表的地址找到对应地址,并根据变量的类型读取相应范围的数据。(内存的最小存储单位为1个字节)(int型变量占4个字节,float也是4个字节,double是8个字节)
《C语言语法知识》-- 指针_第1张图片

通常我们所说的指针,就是地址的意思。C 语言中有专门的指针变量用于存放指针,跟普通变量不同,指针变量存储的是一个地址。它定义时的类型就是存放的地址所指向的数据的类型。
《C语言语法知识》-- 指针_第2张图片
看图,上边我们又定义了两个指针变量:pa 和 pb,因为它们是指针变量,所以它们在内存中存放的是地址。这里我们分别存放了变量 a 和 f 的地址。在我们的编译系统中,指针变量是占 4 个字节的空间,也就是说一个地址是占 4 个字节的空间。(要注意这是针对32位机,64位机是8个字节。在32位、64位系统当中,唯一改变的是指针的长度;在32位系统当中是4个字节、64位则是8个字节。所谓的32位、64位,这个指的是寄存器的位宽。)

取地址运算符和取值运算符:
如果需要获取某个变量的地址,可以使用取地址运算符(&):

char *pa = &a;
int *pb = &f;

如果需要访问指针变量指向的数据,可以使用取值运算符(*):

printf("%c, %d\n", *pa, *pb);

这里要注意的是取值运算符跟定义指针用的都是星号(*),这属于符号的重用,在不同的地方有不同的意义:在定义时表示定义一个指针变量;在其他位置表示获取指针变量指向的变量的值。
直接通过变量名来访问变量的值,我们称之为直接访问;通过指针变量这样的形式来访问变量的值,我们称之为间接访问,所以取值运算符有时候也叫间接运算符。


注意:要避免访问未初始化的指针

#include 

int main()
{
    int *a;

    *a = 123;

    return 0;
}

类似于上边这样的代码是很危险的,因为指针变量 a 到底指向哪里,我们没办法知道。这个道理就跟访问未初始化的变量一样,它的值是随机的。
这在指针变量里会很危险,因为后边代码对一个未知地址进行赋值,那么你可能会覆盖到系统的一些关键代码。不过你也别高兴得太早,因为系统通常都不会允许你这么干,程序这时候会被终止并报错。
更危险的是,偶尔这个指针变量里随机存放的是一个合法的地址,那么接下来的赋值就会导致那个位置的值莫名其妙地被修改。这种类型的 Bug 是非常难以排查的。
所以,在对指针进行间接访问时,必须确保它们已经被正确地初始化。

也就是说在我们定义完指针变量后,要给这个变量赋一个地址,使其初始化。

为了更深入理解指针,请看以下例程:

 #include 

 int main()
 {
    char a = 'F';
    int f = 123;

    char *pa = &a;
    int *pb = &f;

    printf("a = %c\n", *pa);
    printf("f = %d\n", *pb);

    *pa = 'C';
    *pb += 1;

    printf("now, a = %c\n", *pa);
    printf("now, f = %d\n", *pb);

    printf("sizeof pa = %d\n", sizeof(pa));
    printf("sizeof pb = %d\n", sizeof(pb));

    printf("sizeof *pa = %d\n", sizeof(*pa));
    printf("sizeof *pb = %d\n", sizeof(*pb));

    printf("the addr of a is: %p\n", pa);
    printf("the addr of f is: %p\n", pb);

    return 0;
}

该程序的执行结果如图
《C语言语法知识》-- 指针_第3张图片

你可能感兴趣的:(C语言语法知识)