Skip to content

Latest commit

 

History

History
389 lines (233 loc) · 10.7 KB

编程语言.md

File metadata and controls

389 lines (233 loc) · 10.7 KB

[TOC]

编程语言

一、C/C++

001 判断struct的字节数

一般使用sizeof判断struct所占的字节数,那么计算规则是什么呢?

关键词:

1.变量的起始地址和变量自身的字节数

2.以最大变量字节数进行字节对齐(倍数关系)。

注:这里介绍的原则都是在没有#pragma pack宏的情况下

先举个例子:

struct A
{
    char a[5];
    int b;
    short int c;
}struct A;

在上例中,要计算 sizeof(a) 是多少?

有两个原则: 1)各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数 即当 A中的a占用了5个字节后,b需要占用四个字节,此时如果b直接放在a后,则b的起始地址是5,不是sizeof(int)的整数倍,所以 需要在a后面补充3个空字节,使得b的起始地址为8. 当放完b后,总空间为5+3+4 = 12. 接着放c,此时为 12 + 2 = 14.

2)为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数, 所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。 这是说A中占用最大空间的类型,就是int型了,占用了4个字节,那么规定A占用的空间必须是4的整数倍。本来计算出来占用的空间为14, 不是4的整数倍,因此需要在最后补充2个字节。最终导致A占用的空间为16个字节。

再举个例子:

struct B
{
    char *d;
    short int e;
    long long f;
    char c[1];
}b;
 
void test2() {
	printf("%d\n", sizeof(b));
}

对于此题,需要注意的一点是:windows系统对long long是按照8字节进行对齐的,但是Linux系统对long long则是按照4字节对齐的。

因此: d占用4字节(因为d是指针)

e占用2字节

f占用8字节,但是其起始地址为为6,不是4的整数倍(对于Linux系统),或不是8的整数倍(对于Windows系统),因此对e之后进行字节补齐,在这里不管对于Linux还是Windows都是补充2个字节,因此 f 的起始地址是8,占用8个字节。

对于c,它占用了1个字节,起始地址是16,也是1的整数倍。 

最后,在c之后需要对整个B结构体占用的空间进行补齐,目前占用空间是16+1 = 17个字节。

对于Linux,按4字节补齐(long long 是按4字节补齐的),因此补充了3位空字节,最后占用空间是 17 + 3 = 20字节。

对于Windows系统,是按8字节补齐的,因此就补充了7个字节,最后占用的空间是24字节。

参考:

【C++】计算struct结构体占用的长度

002 static作用(修饰变量和函数)

什么是static?

static 是C++中很常用的修饰符,它被用来控制变量的存储方式和可见性。

为什么要引入static?

函数内部定义的变量,在程序执行到它的定义处时,编译器为它在栈上分配空间,大家知道,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题: 如果想将函数中此变量的值保存至下一次调用时,如何实现? 最容易想到的方法是定义一个全局的变量,但定义为一个全局变量有许多缺点,最明显的缺点是破坏了此变量的访问范围(使得在此函数中定义的变量,不仅仅受此函数控制)。

static的作用

第一个作用是限定作用域(隐藏);第二个作用是保持变量内容持久化;

  • 函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值。

举个例子

#include<iostream>

using namespace std;

int main(){

    for(int i=0; i<10; ++i){
	    int a = 0;
		static int b = 0;
		cout<<"a: "<< a++ <<endl;
		cout<<"b(static): " << b++ <<endl;
	}
	return 0;
}

输出结果:

a: 0
b(static): 0
a: 0
b(static): 1
a: 0
b(static): 2
a: 0
b(static): 3
a: 0
b(static): 4
a: 0
b(static): 5
a: 0
b(static): 6
a: 0
b(static): 7
a: 0
b(static): 8
a: 0
b(static): 9
  • 在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外其他函数访问

  • 在模型内的static函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内。

  • 在类中的static成员变量属于整个类所有,对类的所有对象只有一份复制。即类的所有对象访问的static成员变量是同一个,而不是对象专属的。

  • 在类中的static成员函数属于整个类所有,这个函数不接收this指针,因而只能访问类的static成员变量。同类的static成员变量性质一样,类的对象访问的static成员函数是同一个,不是对象专属的。

参考

003 Const作用(修饰变量和函数)

  • TODO

004 多态

  • TODO

005 虚函数

  • TODO

006 继承

  • TODO

007 多线程的同步问题

  • TODO

008 C++的设计模式

  • 工厂模式
  • 策略模式
  • 适配器模式
  • 单例模式
  • 原型模式
  • 模板模式
  • 建造者模式
  • 外观模型
  • 组合模式
  • 代理模式
  • 享元模式
  • 桥接模式
  • 装饰模式
  • 备忘录模式
  • 中介者模式
  • 职责链模式
  • 观察者模式

参考资料

009 动态内存管理

  • TODO

010 智能指针

  • TODO

011 long long转成string

  • TODO

012 NULL和nullstr的区别

  • TODO

013 delete和delete []区别

  • TODO

014 C++虚函数的实现机制

  • TODO

015 C++基类的析构函数为什么建议是虚函数

  • TODO

016 STL中的vector和list的区别

  • TODO

017 多线程和多进程的区别

进程:系统进行资源分配和调度的基本单位。

线程:基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。(有种说法是线程是进程的实体)

线程和进程的关系:

(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程

(2)资源分配给进程,同一个进程的所有线程共享该进程的所有资源

(3)CPU分给进程,即真正在CPU上运行的是线程

参考:多线程与多进程

018 实现atoi,即将"1234"转化成1234(int类型)

  • TODO

019 实现atof,即将"1.234"转换成1.234(float类型)

  • TODO

020 结构体和联合体的区别

结构体:把不同类型的数据组合成一个整体-------自定义数据类型,结构体变量所占内存长度是各成员占的内存长度的总和。

联合体:使几个不同类型的变量共占一段内存(相互覆盖),共同体变量所占内存长度是各最长的成员占的内存长度。

Structure 与 Union主要有以下区别:

1.struct和union都是由多个不同的数据类型成员组成, 但在任何同一时刻, union中只存放了一个被选中的成员, 而struct的所有成员都存在。在struct中,各成员都占有自己的内存空间,它们是同时存在的。一个struct变量的总长度等于所有成员长度之和。在Union中,所有成员不能同时占用它的内存空间,它们不能同时存在。Union变量的长度等于最长的成员的长度。

2.对于union的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于struct的不同成员赋值是互不影响的。

3.联合体的各个成员共用内存,并应该同时只能有一个成员得到这块内存的使用权(即对内存的读写),而结构体各个成员各自拥有内存,各自使用互不干涉。所以,某种意义上来说,联合体比结构体节约内存。

举个例子:

typedef struct
{
int i;
int j;
}A;
typedef union
{
int i;
double j;
}U;

sizeof(A)的值是8,sizeof(U)的值也是8(不是12)。

为什么sizeof(U)不是12呢?因为union中各成员共用内存,i和j的内存是同一块。而且整体内存大小以最大内存的成员的划分。即U的内存大小是double的大小,为8了。

sizeof(A)大小为8,因为struct中i和j各自得到了一块内存,每人4个字节,加起来就是8了。 了解了联合体共用内存的概念,也就是明白了为何每次只能对其一个成员赋值了,因为如果对另一个赋值,会覆盖了上一个成员的值。

举个例子:

例如:书包;可以放置书本、笔盒、记事本等物。

联合体,仅能放入一样东西的包(限制),其尺寸,是可放物品中,最大一件的体积。

结构体,是能放入所有物品的包,所以其尺寸,可同时容纳多样物品。

联合体,同时间只能有一个成员在内。或是说,可以用不同型态,去看同一组数据。

结构体,可以包含多个成员在一起,成员都能个别操作。

021 引用和指针

  • TODO

022 C++ operator new 和 new operator

  • TODO

023 怎么理解C++面向对象?跟Python面向对象有什么区别?

  • TODO

024 C++多态特性,父类和子类的区别

  • TODO

025 虚函数有哪些作用?多态的虚函数(父类和子类)返回值类型可以不一样吗?什么情况下,返回值类型不一样?

  • TODO

026 C++四种强制类型转换有哪些?每种特性是什么?有什么区别?

  • TODO

027 STL中的sort函数实现

  • TODO

028 std::vector描述一下,如何动态扩展,如何shink内存

  • TODO

029 unorder容器与ordered容器的区别

  • TODO

030 说一下智能指针,shared_ptr与unique_ptr

  • TODO

031 说一下什么是虚函数

  • TODO

031 普通指针如何实现一块内存只能有一个指针指向这种功能

  • TODO

032 C++ RTTI 是什么东西?

  • TODO

033 C++是如何实现多态的?

  • TODO

034 vector的iterator什么时候失效?

  • TODO

035 写CmakeLists.txt,写gcc指令

  • TODO

参考资料

二、Python

Python中可变和不可变对象是什么意思?

TODO

三、JAVA

TODO