├── .gitignore ├── 00.md ├── 01.md ├── 02.md ├── 03.md ├── 04.md ├── 05.md ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /00.md: -------------------------------------------------------------------------------- 1 | # 目录 Table Of Contents 2 | 3 | 1. [Chapter 1 - const, inline, static, this](01.md) 4 | 2. [Chapter 2 - pointers, refrence](02.md) 5 | 3. [Chapter 3 - char*, char[], string](03.md) 6 | 4. [Chapter 4 - uint8_t, uint16_t, uint32_t, uint64_t](04.md) 7 | 5. [Chapter 5 - new, delete](05.md) 8 | -------------------------------------------------------------------------------- /01.md: -------------------------------------------------------------------------------- 1 | # Chapter 1 - const, inline,static, this 2 | 3 | ## 1.1 const 4 | 5 | ### (1) const 基础 6 | 7 | 如果const关键字不涉及到指针,我们很好理解,下面是涉及到指针的情况: 8 | 9 | int b = 500; 10 | const int* a = &b; [1] 11 | int const *a = &b; [2] 12 | int* const a = &b; [3] 13 | const int* const a = &b; [4] 14 | 15 | 如果你能区分出上述四种情况,那么,恭喜你,你已经迈出了可喜的一步。不知道,也没关系,我们可以参考《Effective c++》Item21上的做法, 16 | 如果 const 位于星号的左侧,则 const 就是用来修饰指针所指向的变量,即指针指向为常量;如果 const 位于星号的右侧,const 就是修饰指针本身,即指针本身是常量。 17 | 18 | 因此,[1]和[2]的情况相同,都是指针所指向的内容为常量(const放在变量声明符的位置无关),这种情况下不允许对内容进行更改操作,如不能*a = 3;[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;[4]为指针本身和指向的内容均为常量。 19 | 20 | ### (2) 作为参数 21 | 22 | void display(const double& r); 23 | void display(const double* r); 24 | 25 | 说明: 26 | 27 | 1. 在引用或者指针参数的时候使用 const 限制是有意义的,而对于值传递的参数使用 const 则没有意义 28 | 2. 保证引用的变量的值不被改变 29 | 3. const 在 double 前或者后面意思相同,只是不同的人的写法不同 30 | 31 | ### (3) const对象 32 | 33 | 声明为 const 的对象只能访问类中声明为 const 的成员函数,不能调用其它成员函数。 34 | 35 | ### (4) const成员函数 36 | 37 | 类型说明符 函数名(参数表) const; 38 | void print(int i) const; 39 | 40 | 说明: 41 | 42 | 1. const 是函数类型的一个组成部分,因此在实现部分也要带 const 关键字 43 | 2. 常成员函数不能更新对象的数据成员,也不能调用该类中没有用 const 修饰的成员函数 44 | 45 | ### (5) 使用const的一些建议 46 | 47 | 1. 要大胆的使用 const,这将给你带来无尽的益处,但前提是你必须搞清楚原委 48 | 2. 要避免最一般的赋值操作错误,如将 const 变量赋值,具体可见思考题 49 | 3. 在参数中使用 const 应该使用引用或指针,而不是一般的对象实例,原因同上 50 | 4. const 在成员函数中的三种用法(参数、返回值、函数)要很好的使用 51 | 5. 不要轻易的将函数的返回值类型定为 const 52 | 6. 除了重载操作符外一般不要将返回值类型定为对某个对象的 const 引用 53 | 54 | ## 1.2 inline 55 | 56 | ### (1) 预处理宏 57 | 58 | 介绍内联函数之前,有必要介绍一下预处理宏。内联函数的功能和预处理宏的功能相似。相信大家都用过预处理宏,我们会经常定义一些宏,如: 59 | 60 | #define TABLE_COMP(x) ((x)>0 ? (x) : 0) 61 | 62 | 就定义了一个宏。 63 | 64 | 为什么要使用宏呢?因为函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。而宏只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率。 65 | 66 | 但是宏也有很多的不尽人意的地方。 67 | 68 | 1. 宏不能访问对象的私有成员。 69 | 2. 宏的定义很容易产生二意性。 70 | 71 | 我们举个例子: 72 | 73 | #define TABLE_MULTI(x) (x*x) 74 | 75 | 我们用一个数字去调用它,TABLE_MULTI(10),这样看上去没有什么错误,结果返回100,是正确的,但是如果我们用TABLE_MULTI(10+10)去调用的话,我们期望的结果是400,而宏的调用结果是(10+10*10+10),结果是120,这显然不是我们要得到的结果。避免这些错误的方法,**一定要给宏的参数都加上括号**。 76 | 77 | #define TABLE_MULTI(x) ((x)*(x)) 78 | 79 | 这样可以确保不会出错,但是,即使使用了这种定义,这个宏依然有可能出错,例如使用TABLE_MULTI(a++)调用它,他们本意是希望得到(a+1)*(a+1)的结果,而实际上呢?我们可以看看宏的展开结果: (a++)*(a++),如果a的值是4,我们得到的结果是5*6=30。而我们期望的结果是5*5=25,这又出现了问题。事实上,在一些C的库函数中也有这些问题。例如: Toupper(*pChar++)就会对pChar执行两次++操作,因为Toupper实际上也是一个宏。 80 | 81 | ### (2) inline 函数 82 | 83 | 我们可以看到宏有一些难以避免的问题,怎么解决呢? 84 | 85 | 下面就是用我要介绍的内联函数来解决这些问题,我们可以使用内联函数来取代宏的定义。而且事实上我们可以用内联函数完全取代预处理宏。 86 | 87 | 内联函数和宏的区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。 88 | 89 | 我们可以用 inline 来定义内联函数,不过,**任何在类的声明部分定义的函数都会被自动的认为是内联函数**。 90 | 91 | 在函数声明或定义中函数返回类型前加上关键字 inline 即把min()指定为内联。 92 | 93 | inline int min(int first, int secend) {/****/}; 94 | 95 | 我们可以把它作为一般的函数一样调用。但是执行速度确比一般函数的执行速度要快。inline 函数对编译器而言必须是可见的,以便它能够在调用点内展开该函数。与非inline函数不同的是,inline函数必须在调用该函数的每个文本文件中定义。当然,对于同一程序的不同文件,如果C++ inline函数出现的话,其定义必须相同。 96 | 97 | 对于由两个文件compute.c和draw.c构成的程序来说,程序员不能定义这样的min()函数,它在compute.c中指一件事情,而在draw.c中指另外一件事情。如果两个定义不相同,程序将会有未定义的行为。 98 | 99 | 为保证不会发生这样的事情,建议把inline函数的定义放到头文件中。在每个调用该inline函数的文件中包含该头文件。这种方法保证对每个inline函数只有一个定义,且程序员无需复制代码,并且不可能在程序的生命期中引起无意的不匹配的事情。 100 | 101 | ### (3) inline 函数的编程风格 102 | 103 | 关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将 inline 放在函数声明前面不起任何作用。如下风格的函数Foo 不能成为内联函数: 104 | 105 | inline void Foo(int x, int y); 106 | // inline 仅与函数声明放在一起 107 | void Foo(int x, int y){} 108 | 109 | 而如下风格的函数Foo 则成为内联函数: 110 | 111 | void Foo(int x, int y); 112 | inline void Foo(int x, int y) 113 | // inline 与函数定义体放在一起{} 114 | 115 | 所以说,C++ inline函数是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。一般地,用户可以阅读函数的声明,但是看不到函数的定义。尽管在大多数教科书中内联函数的声明、定义体前面都加了inline 关键字,但我认为inline 不应该出现在函数的声明中。这个细节虽然不会影响函数的功能,但是体现了高质量C++/C 程序设计风格的一个基本原则:声明与定义不可混为一谈,用户没有必要、也不应该知道函数是否需要内联。 116 | 117 | 定义在类声明之中的成员函数将自动地成为内联函数,例如: 118 | 119 | class A 120 | { 121 | public: 122 | void Foo(int x, int y) { } 123 | // 自动地成为内联函数 124 | } 125 | 126 | 将成员函数的定义体放在类声明之中虽然能带来书写上的方便,但不是一种良好的编程风格,上例应该改成: 127 | 128 | // 头文件 129 | class A 130 | { 131 | public: 132 | void Foo(int x, int y); 133 | } 134 | // 定义文件 135 | inline void A::Foo(int x, int y){} 136 | 137 | 内联函数在C++类中,应用最广的,应该是用来定义存取函数。我们定义的类中一般会把数据成员定义成私有的或者保护的,这样,外界就不能直接读写我们类成员的数据了。对于私有或者保护成员的读写就必须使用成员接口函数来进行。如果我们把这些读写成员函数定义成内联函数的话,将会获得比较好的效率。 138 | 139 | Class sample { 140 | Private: 141 | int nTest; 142 | Public: 143 | int readtest(){ return nTest;} 144 | Void settest(int I) {nTest=I;} 145 | } 146 | 147 | 当然,内联函数也有一定的局限性。就是函数中的执行代码不能太多了,如果,**内联函数的函数体过大,一般的编译器会放弃内联方式**,而采用普通的方式调用函数。这样,内联函数就和普通函数执行效率一样了。 148 | 149 | ## 1.3 static 150 | 151 | ### (1) 隐藏 152 | 153 | 当我们同时编译多个文件时,所有未加 static 前缀的全局变量和函数都具有全局可见性。 154 | 155 | ### (2) 保持变量内容的持久 156 | 157 | 存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和 static 变量,只不过和全局变量比起来,static 可以控制变量的可见范围,说到底 static 还是用来隐藏的。 158 | 159 | ### (3) 默认初始化为 0 160 | 161 | 其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是 **0x00**,某些时候这一特点可以减少程序员的工作量。 162 | 163 | ## 1.4 this 指针 164 | 165 | 先要理解class的意思。class应该理解为一种类型,像int和char一样,是用户自定义的类型。(虽然比 int 和 char 这样 built-in 类型复杂的多,但首先要理解它们一样是类型)。用这个类型可以来声明一个变量,比如int x, myclass my等等。这样就像变量 x 具有 int 类型一样,变量 my 具有 myclass 类型。 166 | 167 | 理解了这个,就好解释 this 了,my 里的 this 就是指向 my 的指针。如果还有一个变量myclass mz,mz 的 this 就是指向 mz 的指针。这样就很容易理解this 的类型应该是 myclass *,而对其的解引用 *this 就应该是一个 myclass 类型的变量。 168 | 169 | 通常在class定义时要用到类型变量自身时,因为这时候还不知道变量名(为了通用也不可能固定实际的变量名),就用this这样的指针来使用变量自身。 170 | 171 | ### (1) this指针的用处 172 | 173 | 一个对象的 this 指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上 this 指针,编译器在编译的时候也是加上 this 的,它作为非静态成员函数的隐含形参,对各成员的访问均通过 this 进行。 174 | 175 | 例如,调用 date.SetMonth(9) <===> SetMonth(&date, 9),this帮助完成了这一转换。 176 | 177 | ### (2) this指针的使用 178 | 179 | 一种情况就是,在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this;另外一种情况是当参数与成员变量名相同时,如this->n = n (不能写成n = n)。 180 | 181 | ### (3) this指针程序示例 182 | 183 | this指针是存在与类的成员函数中,指向被调用函数所在的类实例的地址。根据以下程序来说明 this 指针: 184 | 185 | #include 186 | class Point 187 | { 188 | int x, y; 189 | public: 190 | Point(int a, int b) { x=a; y=b;} 191 | Void MovePoint( int a, int b){ x+=a; y+=b;} 192 | Void print(){ cout<<"x="<x +=a; this-> y+= b;} 206 | 207 | 即可以知道,point1调用该函数后,也就是point1的数据成员被调用并更新了值。即该函数过程可写成 point1.x+= a; point1. y + = b; 208 | 209 | ### (4) 关于this指针的一个精典回答 210 | 211 | 当你进入一个房子后,你可以看见桌子、椅子、地板等,但是房子你是看不到全貌了。对于一个类的实例来说,你可以看到它的成员函数、成员变量,但是实例本身呢?this 是一个指针,它时时刻刻指向你这个实例本身。 212 | 213 | ## 导航 214 | * [目录](00.md) 215 | * 下一章:[Chapter 2 - pointers, refrence](02.md) -------------------------------------------------------------------------------- /02.md: -------------------------------------------------------------------------------- 1 | # Chapter 2 - pointers, refrence 2 | 3 | ## 2.1 refrence 引用 4 | 5 | 引用是C++中的概念,初学者容易把引用和指针混淆一起。以下程序中,n 是 m 的一个引用(reference),m 是被引用物(referent)。 6 | 7 | int m; 8 | int &n = m; 9 | 10 | n 相当于 m 的别名(绰号),对 n 的任何操作就是对m的操作。所以 n 既不是 m 的拷贝,也不是指向 m 的指针,其实 n 就是 m 它自己。 11 | 12 | **引用的规则:** 13 | 14 | - 引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。 15 | - 不能有NULL引用,引用必须与合法的存储单元关联(指针则可以是NULL)。 16 | - 一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。 17 | 18 | 以下示例程序中,k 被初始化为 i 的引用。语句 k = j 并不能将 k 修改成为 j 的引用,只是把 k 的值改变成为6。由于 k 是 i 的引用,所以 i 的值也变成了6。 19 | 20 | int i = 5; 21 | int j = 6; 22 | int &k = i; 23 | k = j; // k和i的值都变成了6; 24 | 25 | **引用的主要功能是传递函数的参数和返回值**。 26 | 27 | C++语言中,函数的参数和返回值的传递方式有三种:**值传递、指针传递和引用传递**。 28 | 29 | ### (1) 以下是"值传递"的示例程序 30 | 31 | 由于Func1函数体内的x是外部变量n的一份拷贝,改变x的值不会影响n, 所以n的值仍然是0。 32 | 33 | void Func1(int x) 34 | { 35 | x = x + 10; 36 | } 37 | ... 38 | int n = 0; 39 | Func1(n); 40 | cout << "n = " << n << endl; // n = 0 41 | 42 | ### (2) 以下是"指针传递"的示例程序 43 | 44 | 由于Func2函数体内的x是指向外部变量n的指针,改变该指针的内容将导致n的值改变,所以n的值成为10。 45 | 46 | void Func2(int *x) 47 | { 48 | (* x) = (* x) + 10; 49 | } 50 | ... 51 | int n = 0; 52 | Func2(&n); 53 | cout << "n = " << n << endl; // n = 10 54 | 55 | ### (3) 以下是"引用传递"的示例程序 56 | 57 | 由于Func3函数体内的x是外部变量n的引用,x和n是同一个东西,改变x等于改变n,所以n的值成为10。 58 | 59 | void Func3(int &x) 60 | { 61 | x = x + 10; 62 | } 63 | ... 64 | int n = 0; 65 | Func3(n); 66 | cout << "n = " << n << endl; // n = 10 67 | 68 | 对比上述三个示例程序,**会发现"引用传递"的性质象"指针传递",而书写方式象"值传递"**。 69 | 70 | 实际上"引用"可以做的任何事情"指针"也都能够做,为什么还要"引用"这东西? 71 | 答案是"用适当的工具做恰如其分的工作"。 72 | 73 | 指针能够毫无约束地操作内存中的任何东西,尽管指针功能强大,但是非常危险。 74 | 75 | 如果的确只需要借用一下某个对象的"别名",那么就用"引用",而不要用"指针",以免发生意外。 76 | 77 | ## 导航 78 | * [目录](00.md) 79 | * 上一章:[Chapter 1 - const, inline,static, this](01.md) 80 | * 下一章:[Chapter 3 - char*, char[], string](03.md) -------------------------------------------------------------------------------- /03.md: -------------------------------------------------------------------------------- 1 | # Chapter 3 - char*, char[], string 2 | 3 | ## 3.1 char*, char[], string 4 | 5 | 在C中,并没有字符串这个数据类型,而是使用字符数组来保存字符串。C字符串实际上就是一个以null('\0')字符结尾的字符数组,null字符表示字符串的结束。需要注意的是:只有以null字符结尾的字符数组才是C字符串,否则只是一般的C字符数组。 6 | 7 | C字符串定义时可以利用"="号进行初始化,但是以后不能利用"="对C字符串进行赋值。对C字符串的操作需要通过"string"文件中定义的字符串处理函数。例如: 8 | 9 | //字符串的初始化 10 | char a[11] = "huanying"; 11 | //字符串的赋值 12 | strcpy(a,"nihao") 13 | //获取字符串的长度,不包括'\0'在内 14 | strlen(a); 15 | printf("%s",a); 16 | 17 | 在C中也可以使用字符指针来访问一个字符串,通过字符指针指向存放字符串数组的首元素地址来进行访问. 18 | char *a = "nihao"; 19 | printf("%s",a); 20 | 21 | 在C++中则把字符串封装成了一种数据类型string,可以直接声明变量并进行赋值等字符串操作。以下是C字符串和C++中string的区别: 22 | 23 | C字符串 string对象 24 | 所需的头文件名称 25 | 为什么需要头文件 为了使用字符串函数 为了使用string类 26 | 如何声明 char name[20]; string name; 27 | 如何初始化 char name[20]="nihao"; string name = "nihao"; 28 | 必须声明字符串长度么? 是 否 29 | 使用一个null字符么? 是 否 30 | 怎样实现字符串赋值 strcpy(name,"John"); name = "John"; 31 | 其他优点 更快 更易于使用,优选方案 32 | 可以赋一个比现有字符更 不能 可以 33 | 长的字符串么? 34 | 35 | ### (1) C++常用字符串函数 36 | 37 | char s1[]="I am a student"; 38 | char s2[20]="teacher"; 39 | char s3[]="student"; 40 | int result; 41 | char s4[20],*p; 42 | 43 | 1. 串长度 int strlen(char *str) 44 | 45 | cout<str2,返回1 57 | 58 | result=strcmp(s2,s3); //result>0 59 | result=strcmp(s2,s2); //result=0 60 | result=strcmp(s3,s2); //result<0 61 | 62 | 5. 串定位 char *strchr(char *str,char ch) 63 | 64 | p=strchr(s1,'s'); //找到返回字符在字串中的位置,否则返回-1 65 | strcpy(p,s2); //s1为"I am a teacher" 66 | 67 | 6. 在一个串中查找是否存在和另一个串相等的子串 68 | 69 | 7. 截取子串形成一个新串 70 | 71 | ### (2) 字符串的输入 72 | 73 | 1. 方法一:使用输入操符来填充一个C字符串变量 74 | 例如: 75 | char a[80]; 76 | cin>>a; 77 | 注:以这种方式来读取C字符串时,会忽略最初的空白字符(空格、制表符和换行符),而且输入会在下一个空格或者换行符处停止。 78 | 79 | 2. 方法二:使用预定义函数getline获取整行输入(包括空格) 80 | getline函数有两个参数:第一个参数用于接收输入的C字符串变量;第二个参数用于规定getline最多能接收的字符个数。 81 | 例如: 82 | char a[80]; 83 | cin.getline(a,80); 84 | 当遇到行结束的时候,输入才会停止。 85 | 86 | ### (3) C++ string类的输入 87 | 88 | 1. 方法一:和C字符串输入的方法一相同。 89 | 2. 方法二:使用getline函数。 90 | 91 | 例如: 92 | 93 | string a; 94 | getline(cin,a); 95 | 96 | ### (4) string对象和C字符串之间的转换 97 | 98 | 可以将C字符串存储在string类型的变量中,例如: 99 | 100 | char a[] = "nihao"; 101 | string b; 102 | b=a; 103 | 104 | 但string对象不能自动的转换为C字符串,需要进行显式的类型转换,需要用到string类的成员函数c_str(). 105 | 例如: 106 | 107 | strcpy(a,b.c_str()); 108 | 109 | 110 | ### (5) 字符串到数字的转换 111 | 112 | atoi函数获取一个C字符串参数,返回对应的int值。如果参数不与一个int值对应,atoi就会返回0。atoi函数在文件为cstdlib的库中。如果数字太大,不能转换成int类型的值,可以使用atol将字符串转换为long类型的值。 113 | 例如: 114 | 115 | atoi("1234"); //返回整数1234 116 | atoi("#123"); //返回0 117 | 118 | ## 导航 119 | * [目录](00.md) 120 | * 上一章:[Chapter 2 - pointers, refrence](02.md) 121 | * 下一章:[Chapter 4 - uint8\_t, uint16\_t, uint32\_t, uint64\_t](04.md) -------------------------------------------------------------------------------- /04.md: -------------------------------------------------------------------------------- 1 | # Chapter 4 - uint8\_t, uint16\_t, uint32\_t, uint64\_t 2 | 3 | uint8\_t, uint16\_t, uint32\_t, uint64\_t 是什么数据类型? 4 | 5 | 那么_t的意思到底表示什么?它就是一个结构的标注,可以理解为type/typedef的缩写,表示它是通过typedef定义的,而不是其它数据类型。 6 | 7 | uint8\_t,uint16\_t,uint32\_t 等都不是什么新的数据类型,它们只是使用typedef给类型起的别名,新瓶装老酒的把戏。不过,不要小看了typedef,它对于你代码的维护会有很好的作用。比如C中没有bool,于是在一个软件中,一些程序员使用int,一些程序员使用short,会比较混乱,最好就是用一个typedef来定义,如: 8 | 9 | typedef char bool; 10 | 11 | 一般来说,一个C的工程中一定要做一些这方面的工作,因为你会涉及到跨平台,不同的平台会有不同的字长,所以利用预编译和typedef可以让你最有效的维护你的代码。为了用户的方便,**C99标准的C语言**硬件为我们定义了这些类型,我们放心使用就可以了。 12 | 13 | 按照posix标准,一般整形对应的*_t类型为: 14 | 15 | 1字节 uint8_t 16 | 2字节 uint16_t 17 | 4字节 uint32_t 18 | 8字节 uint64_t 19 | 20 | 附:C99标准中inttypes.h的内容 21 | 22 | 00001 /* 23 | 00002 inttypes.h 24 | 00003 25 | 00004 Contributors: 26 | 00005 Createdby Marek Michalkiewicz 27 | 00006 28 | 00007 THISSOFTWARE IS NOT COPYRIGHTED 29 | 00008 30 | 00009 Thissource code is offered for use in the public domain. You may 31 | 00010 use,modify or distribute it freely. 32 | 00011 33 | 00012 Thiscode is distributed in the hope that it will be useful, but 34 | 00013 WITHOUTANY WARRANTY. ALLWARRANTIES, EXPRESS OR IMPLIED ARE HEREBY 35 | 00014 DISCLAIMED. This includes but is not limited towarranties of 36 | 00015 MERCHANTABILITYor FITNESS FOR A PARTICULAR PURPOSE. 37 | 00016 */ 38 | 00017 39 | 00018 #ifndef __INTTYPES_H_ 40 | 00019 #define __INTTYPES_H_ 41 | 00020 42 | 00021 /* Use [u]intN_t if you need exactly N bits. 43 | 00022 XXX- doesn't handle the -mint8 option. */ 44 | 00023 45 | 00024 typedefsigned char int8_t; 46 | 00025 typedefunsigned char uint8_t; 47 | 00026 48 | 00027 typedefint int16_t; 49 | 00028 typedefunsigned int uint16_t; 50 | 00029 51 | 00030 typedeflong int32_t; 52 | 00031 typedefunsigned long uint32_t; 53 | 00032 54 | 00033 typedeflong long int64_t; 55 | 00034 typedefunsigned long long uint64_t; 56 | 00035 57 | 00036 typedefint16_t intptr_t; 58 | 00037 typedefuint16_t uintptr_t; 59 | 00038 60 | 00039 #endif 61 | 62 | ## 导航 63 | * [目录](00.md) 64 | * 上一章:[Chapter 3 - char*, char[], string](03.md) 65 | * 下一章:[Chapter 5 - new, delete](05.md) -------------------------------------------------------------------------------- /05.md: -------------------------------------------------------------------------------- 1 | # Chapter 5 - new, delete 2 | 3 | new和delete运算符用于动态分配和撤销内存的运算符 4 | 5 | ### (1) new用法 6 | 7 | 1. 开辟单变量地址空间 8 | 9 | 1) new int; //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a = new int 即为将一个int类型的地址赋值给整型指针a. 10 | 11 | 2) int *a = new int(5) 作用同上,但是同时将整数赋值为5 12 | 13 | 2. 开辟数组空间 14 | 15 | 一维: 16 | 17 | int *a = new int[100]; // 开辟一个大小为100的整型数组空间 18 | 19 | 二维: 20 | 21 | int **a = new int[5][6] 22 | 23 | 三维及其以上:依此类推 24 | 25 | 一般用法: new 类型 [初值] 26 | 27 | ### (2) delete用法 28 | 29 | 1. int *a = new int; 30 | 31 | delete a; //释放单个int的空间 32 | 33 | 2. int *a = new int[5]; 34 | 35 | delete [] a; //释放int数组空间 36 | 37 | 要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问。 38 | 39 | 用new和delete可以动态开辟,撤销地址空间。在编程序时,若用完一个变量(一般是暂时存储的数组),下次需要再用,但却又想省去重新初始化的功夫,可以在每次开始使用时开辟一个空间,在用完后撤销它。 40 | 41 | ## 导航 42 | * [目录](00.md) 43 | * 上一章:[Chapter 4 - uint8\_t, uint16\_t, uint32\_t, uint64\_t](04.md) 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Andy Cai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | c/c++ primer 2 | ======= 3 | 4 | 1. [Chapter 1 - const, inline, static, this](01.md) 5 | 2. [Chapter 2 - pointers, refrence](02.md) 6 | 3. [Chapter 3 - char*, char[], string](03.md) 7 | 4. [Chapter 4 - uint8_t, uint16_t, uint32_t, uint64_t](04.md) 8 | 5. [Chapter 5 - new, delete](05.md) 9 | --------------------------------------------------------------------------------