重新温习了一遍 C 的指针,感觉当前(也就是前年)不明白的地方现在真的有种豁然开朗的感觉。

# Memory in C

# Static Memory

  • 全局变量,可以被整个程序访问到。
  • static 关键字描述的局部变量,也和全局变量类似,在程序运行时就会完成初始化,但是它对其他程序隐藏。(虽然是局部变量,但是在程序运行时进行初始化)

# Stack Memory

  • 局部变量将会在函数结束时候进行回收。

# Heap Memory

  • 由程序员进行申请的变量,需要自己进行 free,否则会有内存溢出。

# what is pointer?

指针说白了就是一个 int64 的值,这个 int64 的值指向了内存的地址空间,理论上来说,C 语言中所有的变量都可以用指针来描述,因为它们也是保存在内存中的。

来看这个例子:

char* makeABC() {
    char y[3] = {'a', 'b', 'c'};
    return y;
}
int main()
{
    char * t=  makeABC();
    printf("%s", t);
    exit(0);
}

这个函数会报错,会说 y 不是 const char * 。原因就是 y 字符数组是局部变量,因此在函数结束后就会被堆栈进行回收,无法进行返回。

一个非常有意思的改动:

char* makeABC() {
    char y[3] = {'a', 'b', 'c'};
    char *p = y;
    return p;
}

成功打印了输出!

abc

再对 main 函数进行修改:

int main()
{
    char * t=  makeABC();
    sleep(3);
    printf("%s", t);
    exit(0);
}

输出结果:

image-20220326152946278

看上去出现了内存溢出,这是因为在 C 中,堆栈回收不是删除数据,而是直接将堆栈的指针复位。原本内存的数据通过指针 p 进行访问,但是这段内存段可能正在 main 函数 sleep 3s 的时候,被别的程序写,这就导致出现了乱码。

# 强制类型转换

上面已经提到了,程序运行时数据保存在以 01 方式保存在内存中,那么我们如何将这些 01 数据变成我们需要的类型。这就编译器做的。

int a = 2;
float b = (float)a;
printf("%f \n", b);

上面两行代码就是简单的类型转换,做的事情就是编译器先把一段 01 数据转换为 int 类型的 2,再将 int 类型转换 float 类型。

# 指针类型转换

指针其实就是一个 int64 的值,它指向了一段内存地址,这个内存里的值到底是什么,就需要编译器来处理。

所以如果对指针进行类型转换,比如:

int a = 2;
float* b = (float*)&a
printf("%f \n", *b);

这个代码告诉编译器,请把保存变量 a 的内存地址中的 01bit 数据解释为 float 类型保存的数据。

打印输出: 0.000000

这是因为 float 类型的保存为:

image-20220326154658681

int 2,在内存中保存为 10 。转换为 float 类型来解释后,这个 01 就是尾数,打印输出时候就会忽略,因为就打印了 0.00000。

# 特殊的 Void 指针

void 指针有点像 go 里面的空接口,可以传递任何类型的指针。

更新于

请我喝[茶]~( ̄▽ ̄)~*

Kalice 微信支付

微信支付

Kalice 支付宝

支付宝