C/C++总结1


  斑马斑马      50   
  2021-01-13      C++      

  • 前言 : …

1 计算机基础

1.1 C/C++内存有哪几种类型?

  • C中,内存分为5个区:堆(malloc)、栈(如局部变量、函数参数)、程序代码区(存放二进制代码)、全局/静态存储区(全局变量、static变量)和常量存储区(常量)。此外,C++中有自由存储区(new)一说。

  • 全局变量、static变量会初始化为零,而堆和栈上的变量是随机的,不确定的。

1.2 堆和栈的区别?

  • 堆存放动态分配的对象——即那些在程序运行时动态分配的对象,比如 new 出来的对象,其生存期由程序控制;

  • 栈用来保存定义在函数内的非static对象,如局部变量,仅在其定义的程序块运行时才存在;

  • 静态内存用来保存static对象,类static数据成员以及定义在任何函数外部的变量,static对象在使用之前分配,程序结束时销毁;

  • 栈和静态内存的对象由编译器自动创建和销毁。

1.3 堆和自由存储区的区别?

  • 总的来说,堆是C语言和操作系统的术语,是操作系统维护的一块动态分配内存;自由存储是C++中通过new与delete动态分配和释放对象的抽象概念。他们并不是完全一样。

  • 从技术上来说,堆(heap)是C语言和操作系统的术语。堆是操作系统所维护的一块特殊内存,它提供了动态分配的功能,当运行程序调用malloc()时就会从中分配,稍后调用free可把内存交还。而自由存储是C++中通过new和delete动态分配和释放对象的抽象概念,通过new来申请的内存区域可称为自由存储区。基本上,所有的C++编译器默认使用堆来实现自由存储,也即是缺省的全局运算符new和delete也许会按照malloc和free的方式来被实现,这时藉由new运算符分配的对象,说它在堆上也对,说它在自由存储区上也正确。

1.4 程序编译的过程?

  • 程序编译的过程中就是将用户的文本形式的源代码(c/c++)转化成计算机可以直接执行的机器代码的过程。主要经过四个过程:预处理、编译、汇编和链接。具体示例如下。

  • 一个hello.c的c语言程序如下。

#include <stdio.h>
int main()
{
    printf("happy new year!\n");
    return 0;
}
  • 其编译过程如下:
    C/C++总结1 - 第1张

1.5 计算机内部如何存储负数和浮点数?

  • 负数比较容易,就是通过一个标志位和补码来表示。

  • 对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit,double数据占用64bit,我们在声明一个变量float f = 2.25f的时候,是如何分配内存的呢?如果胡乱分配,那世界岂不是乱套了么,其实不论是float还是double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53。更多可以参考浮点数表示。

  • 无论是单精度还是双精度在存储中都分为三个部分:
    1). 符号位(Sign):0代表正,1代表为负
    2). 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储
    3). 尾数部分(Mantissa):尾数部分

  • 其中float的存储方式如下图所示:

    C/C++总结1 - 第2张

  • 而双精度的存储方式如下图:

    C/C++总结1 - 第3张

1.6 函数调用的过程?

如下结构的代码:

int main(void)
{
  ...
  d = fun(a, b, c);
  cout<<d<<endl;
  ...
  return 0;
}

调用fun()的过程大致如下:

main()========
1).参数拷贝(压栈),注意顺序是从右到左,即c-b-a;
2).保存d = fun(a, b, c)的下一条指令,即cout<<d<<endl(实际上是这条语句对应的汇编指令的起始位置);
3).跳转到fun()函数,注意,到目前为止,这些都是在main()中进行的;
fun()=====
4).移动ebp、esp形成新的栈帧结构;
5).压栈(push)形成临时变量并执行相关操作;
6).return一个值;
7).出栈(pop);
8).恢复main函数的栈帧结构;
9).返回main函数;
main()========
。。。

1.7 左值和右值

不是很严谨的来说,左值指的是既能够出现在等号左边也能出现在等号右边的变量(或表达式),右值指的则是只能出现在等号右边的变量(或表达式)。举例来说我们定义的变量 a 就是一个左值,而malloc返回的就是一个右值。或者左值就是在程序中能够寻值的东西,右值就是一个具体的真实的值或者对象,没法取到它的地址的东西(不完全准确),因此没法对右值进行赋值,但是右值并非是不可修改的,比如自己定义的class,可以通过它的成员函数来修改右值。

1.8 什么是内存泄漏?面对内存泄漏和指针越界,你有哪些方法?你通常采用哪些方法来避免和减少这类错误?

用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元即为内存泄露。

1). 使用的时候要记得指针的长度.
2). malloc的时候得确定在那里free.
3). 对指针赋值的时候应该注意被赋值指针需要不需要释放.
4). 动态分配内存的指针最好不要再次赋值.
5). 在C++中应该优先考虑使用智能指针.

2 C/C++

3 数组-指针-引用

4 C++

作者:Sara&Ben

ps:以上是C/C++总结1全部内容,希望文章能够帮你解决C/C++总结1所遇到的游戏开发问题。
本文收录在 游戏编程 🕹️ - 学习C++专题,分享走一走~

猜你喜欢 全系列


您可以在登录后,发表评论