指针4

112 阅读2分钟

「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。

下面我们来看一段有关静态变量不能跨函数使用的代码:

# include<stdio.h>

void f(int **q)
{
    int i = 5;
    *q = &i;
}

int main(void)
{
    int *p;
    
    f(&p);
    printf("%d\n",*p);
    
    return 0;
}

image.png

q是个指针变量,无论q是什么类型的指针变量,都只占4个字节。
*q等价于p。**q代表的是指针变量的地址。其实这段代码逻辑上有点小问题:

f(&p)执行完之后,为其分配的内部的静态变量i会被释放不能被外部使用,而输出语句中的*p确指向了它,只有指针才会出现这个问题,访问了它不该访问的地方。p能保存i地址,但不能访问i的空间,所以说静态变量不能跨函数使用。静态内存是在栈里面分配的.

下面再举一个动态内存可以跨函数使用的代码:

#include<stdio.h>
#include<malloc.h>

void f(int **q)
{
    *q = (int *)malloc(sizeof(int));
    //q = 5;//error
    //*q = 5;//p = 5
    **q = 5;//*p = 5
}

int main(void)
{
    int * p;
    
    f(&p);
    
    return 0;
}

image.png

写sizeof(数据类型)返回值是增强了代码的可移植性,动态内存是在堆里面分配的,所以出栈不出栈跟内存没关系,所以4个字节的sizeof(int)仍然保存着,f(&p)终止后,仍然能调用,所以最关键的还是内存为其分配的空间是否能使用,而最好的办法就是用动态内存.动态内存的分配必须调用free()函数才能释放,而自动变量一旦跳出它的代码作用范围,就会由编译器自动释放掉.

综上所述:各有各的好,实战中发挥各自的优势才能提高效率.

为了表示一些复杂的事物,而普通的基本类型无法满足实际需求,所以我们引入结构体这个概念. 简单来说,结构体就是把一些基本类型数据组合在一起形成的一个新的数据类型. 定义结构体的三种方式: 第一种方式:

image.png 第二种方式:

image.png 第三种方式:

image.png

以上三种方式,只建议使用第一种.