美文网首页C++面试程序员
C 堆变量,栈变量,指针参数,非指针参数 它们的区别你了解嘛

C 堆变量,栈变量,指针参数,非指针参数 它们的区别你了解嘛

作者: Linux后端研发工程实践 | 来源:发表于2017-03-26 11:20 被阅读57次

1.基本概念

  • 堆(Heap)
    程序可以动态申请的存储空间,通过malloc系列函数分配,全局可访问。

  • 栈(Stack)
    这里说的栈不是数据结构中LIFO的栈,而是进程虚拟地址空间的栈;程序在进行函数调用时动态伸缩的存储空间,局限于函数内可以访问。

-堆变量(Heapvariables)
数据存储在堆的变量,全局可访问。

  • 栈变量(Stackvariables)
    函数中声明的局部变量,只能在函数内部访问,否则访问行为的结果是未定义的。

  • 指针参数(Pointerparameters)
    参数类型为指针的参数。

  • 非指针参数(Non-pointerparameters)
    参数类型不是指针的参数。

2.进程的虚拟地址空间

进程虚拟地址空间

3.相关问题剖析

3.1 如何正确的分配内存

demo代码

void * fun_m1()
{
    char buf[100];
    return (void *)buf;
}

void * fun_m2(size_t size)
{
    return malloc(size);
}

void fun_m3(size_t size, void * p)
{
    p = malloc(size);
}

void fun_m4(size_t size, void ** p)
{
    *p = malloc(size);
}

剖析

  • fun_m1是错误的,因为它返回的栈变量的地址,如果对它指向的地址进行读写,程序行为的结果是未定义的,程序很可能崩溃,因为此时栈变量的空间已经被回收(栈顶指针改变了)。
  • fun_m2是正确的,因为它返回的是malloc申请的堆空间的地址。
  • fun_m3和fum_m4很具有迷惑性,要分区fun_m3和fun_m4的区别,我们这里需要澄清一个概念:任何的参数传递本质上都是值拷贝,任何参数都是栈变量。
  • 在我们以往观念中参数传递就是两种:值传递,指针传递,而通过指针可以改变指针指向的变量。
  • 为什么说参数传递都是值拷贝呢,这是因为不管参数是否为指针,传递的都是一份值的拷贝,只不过当你的参数类型为指针时,你传递的是指针变量的值,而通过*操作符作用在指针变量上,你又刚好可以影响到指针变量关联的其他变量的值。
  • 通过上面的剖析我们可以知道fun_m3是错误的,因为没有*操作符作用在p上,单纯对p赋值操作只会影响到局部的栈变量p的值,而不会对函数fun_m3外的变量有任何影响。fun_m4是正确的,因为有*操作符作用在p上,通过对*p赋值来修改传递给p的参数,使它指向申请的堆空间。

3.2 如何判断堆和栈的“增长”方向(从低到高,还是从高到低)

判断栈的“增长”方向

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

void fun1(int * pb)
{
    int a;
    printf("stack alloc direction[%s]\n", &a > pb ? "Up" : "Down");
}

void fun2()
{
    int b;
    fun1(&b);
}

int main()
{
    fun2();
    return 0;
}

编译运行

[root@iZ940zytujjZ test]# gcc -o test10 test10.c
[root@iZ940zytujjZ test]# ./test10
stack alloc direction[Down]
[root@iZ940zytujjZ test]#

从运行结果看,栈的增长方向是“从高到低”(Down)。

判断堆的“增长”方向

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

int main()
{
    void * a = sbrk(10);    //调整堆顶指针brk
    void * b = sbrk(20);
    printf("heap alloc direction[%s]\n", b > a ? "Up" : "Down");
    return 0;
}

编译运行

[root@iZ940zytujjZ test]# gcc -o test11 test11.c
[root@iZ940zytujjZ test]# ./test11
heap alloc direction[Up]
[root@iZ940zytujjZ test]#

从运行结果看,堆的增长方向是“从低到高”(Up)。

相关文章

  • C 堆变量,栈变量,指针参数,非指针参数 它们的区别你了解嘛

    1.基本概念 堆(Heap)程序可以动态申请的存储空间,通过malloc系列函数分配,全局可访问。 栈(Stack...

  • 指针函数,函数指针,和位运算

    1.函数指针和指针函数的区别 函数指针是指向函数的指针变量,即本质是一个指针变量 指针函数可用于将一个函数作为参数...

  • 【C++】指针传递与函数返回详解

    指针变量作为参数传递给函数的时候,编译器会将这个指针变量Copy一份,也就说在函数内部使用的这个参数变量,是另外一...

  • C++笔记

    c++名词解惑# 一。堆和栈的区别:++++++栈: FILO os自动分配释放,函数参数,局部变量等。 一级缓存...

  • 二、C语言基础

    A、指针 指针的概念:指针变量 和 指针 的区别 ?答:指针变量是指针的标记,也可以通过指针变量的标记操作指针内存...

  • iOS面试基础

    堆和栈的区别 指针常量和常量指针 不借助第三个变量,交换两个变量的值 iOS反射机制 iOS为什么在主线程刷新UI...

  • 栈、堆、全局存储区、文字常量区、程序代码区

    栈区 内存管理由系统控制,存储的为 非静态的局部变量,例如:函数参数,在函数中生命的对象的指针等。当系统的栈区大小...

  • 函数指针

    1.定义一个无参数无返回值的函数指针 (*p):是固定写法,代表指针变量将来肯定指向函数的 左边void:指针变量...

  • C语言

    C 指针、指针变量、函数指针、指针函数、指针数组、数组指针、C 数组

  • Head First C 学习之指针和数组的区别

    数组与指针: · 数组变量可以被用着指针· 数组变量指向数组中第一个元素· 如果函数参数声明为数组,...

网友评论

    本文标题:C 堆变量,栈变量,指针参数,非指针参数 它们的区别你了解嘛

    本文链接:https://www.haomeiwen.com/subject/wdzhottx.html