![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
C
文章平均质量分 58
加油11
模仿模仿再模仿!
展开
-
内存这个大话题
1 程序运行为什么需要内存1.1 计算机程序运行的目的计算机为什么需要编程?编程已经编了很多年,已经写了很多程序,为什么还需要另外写程序?计算机有这个新的程序到底为了什么?程序的目的是为了去运行,程序运行是为了得到一定的结果。计算机就是用来计算的,所有的计算机程序其实都是在做计算。计算就是在计算数据。所以计算机程序中很重要的部分就是数据。计算机程序 = 代码 + 数据。计算机程原创 2018-01-05 17:33:01 · 558 阅读 · 0 评论 -
函数与指针分析
1 函数类型(1)C语言中的函数有自己特定的类型。(2)函数的类型由返回值,参数类型和参数个数共同决定。 int add(int j, int k)的类型为int(int, int)。(3)C语言中通过typedef为函数类型重命名。 typedef type name(parameter list)。例: typedef int f(int, int); typedef void p(in原创 2017-12-22 11:37:01 · 216 阅读 · 0 评论 -
#line使用分析
1 #line的用法#line用于强制指定新的行号和编译文件名,并对源程序的代码重新编号。 用法:#line number filename (filename可省略)。#line编译指示字的本质是重定义 __LINE__ 和 __FILE__。编程实验:#line的使用#include <stdio.h>// The code section is written by A.// Beg原创 2017-11-23 22:07:01 · 1256 阅读 · 0 评论 -
#和##操作符使用分析
1 #运算符#运算符用于在预处理期将宏参数转换为字符串。#的转换作用是在预处理完成的,因此只在宏定义中有效。编译器不知道#的转换作用。用法: #define STRING(x) #x printf(“#s.\n”, STRING(Hello World!));实例分析:#运算符的基本用法#include <stdio.h>#define STRING(x) #xint main()原创 2017-11-27 22:06:14 · 239 阅读 · 0 评论 -
数组参数和指针参数分析
1 思考为什么C语言中的数组参数会退化为指针?2 退化的意义C语言中只会以值拷贝的方式传递参数。当向函数传递数组时由如下两种实现方式:将整个数组拷贝一份传入函数;将数组名看作常量指针传数组首元素地址(C语言采用的方式)。C语言以高效作为最初设计目标:参数传递的时候如果拷贝整个数组执行效率将大大下降。参数位于栈上,太大的数组拷贝将导致栈溢出。3 二维数组参数二维数组参数同样存在退化的问题原创 2017-12-21 09:59:07 · 243 阅读 · 0 评论 -
指针和数组分析
1 数组的本质数组是一段连续的内存空间。数组的空间大小为sizeof(array_type)*array_size。数组名可看作指向数组第一个元素的常量指针。问题: 1. a + 1的意义是什么?结果是什么? 2. 指针运算的意义是什么?结果又是什么?编程实验:a + 1的结果是什么?#include <stdio.h>int main(){ int a[5] = {0};原创 2017-11-29 20:56:15 · 240 阅读 · 0 评论 -
main函数与命令行参数
1 main函数的概念C语言中main函数称之为主函数。一个程序是从main函数开始执行的。下面的main函数定义正确吗?main(){}void main(){}int main(){}int main(){return 0;}2 main函数的本质main函数是操作系统调用的函数。操作系统总是将main函数作为应用程序的开始。操作系统将main函数的返回值作为程序的退出状态原创 2017-12-02 21:02:02 · 482 阅读 · 0 评论 -
#error和#warning使用分析
1 #error的用法error用于生成一个编译错误消息。 用法:#error message(message不需要用双引号包围)。#error编译指示字用于自定义程序员特有的编译错误消息,类似的#warning用于生成编译警告。#error是一种预编译器指示字。#error可用于提示编译条件是否满足。例如:#ifnedf __cplusplus #error This fil原创 2017-11-23 22:04:10 · 4094 阅读 · 0 评论 -
数组指针和指针数组分析
1 思考下面这些声明合法吗? int array[5]; int matrix[3][3]; int *pa = array; int *pm = matrix;问题: array代表数组首元素的地址,那么matrix代表什么? array和&array的地址值相同,但是意义不同,那么它们所代表的类型相同吗?2 数组类型C语言中的数组有自己特定的类型。数组的类型由元素和数组大小共同决原创 2017-12-02 17:50:38 · 231 阅读 · 0 评论 -
C语言中的字符串
1 字符串的概念字符串是有序字符的集合。字符串是程序中的基本元素之一。C语言中没有字符串的概念。 C语言中通过特殊的字符数组模拟字符串。C语言中的字符串是以‘\0’结尾的字符数组。2 字符数组与字符串在C语言中,双引号引用的单个或多个字符是一种特殊的字面量。 存储于程序的全局只读存储区。本质为字符数组,编译器自动在结尾加上‘\0’字符。下面哪些是字符串的定义? char原创 2017-11-30 21:29:38 · 521 阅读 · 0 评论 -
注释符号
1 注释的第一印象2 似是而非的问题下面的注释是正确的么?#include <stdio.h>int main(){ int/*...*/i; char* s = "abcdefgh //hijklmn"; //Is it a \ valid comment? in/*...*/t i; return 0;}/* 只有最后一句注释是错误的。 */原创 2017-11-06 07:17:09 · 5478 阅读 · 0 评论 -
指针阅读技巧分析
1 笔试中的问题下面的标识符代表什么含义?2 指针阅读技巧解析右左法则:从最里层的圆括号中未定义的标示符看起。首先往右看,再往左看。遇到圆括号或方括号时可以确定部分类型,并调转方向。重复2,3步骤,直到阅读结束。编程实验:复杂指针的阅读#include <stdio.h>int main(){ int (*p)(int); //==>p为指针,指向函数,指向的函数有一个原创 2017-12-22 16:08:42 · 251 阅读 · 0 评论 -
#pragma使用分析
1 #pragma简介#pragma用于指示编译器完成一些特定的动作。#pragma所定义的很多指示字是编译器特有的。#pragma在不同的编译器是不可移植的。 预处理器会忽略它不认识的#pragma指令。不同的编译器可能以不同的方式解释同一条#pragma指令。一般用法:#pragma parameter。 注:不同的parameter参数语法和意义各不相同。2 #pragma m原创 2017-11-26 21:54:45 · 335 阅读 · 0 评论 -
栈、堆、静态存储区和程序的内存布局
1 栈1.1 程序中的栈栈是现代计算机程序里最重要的概念之一。栈在程序中用于维护函数调用上下文。函数中的参数和局部变量存储在栈上。栈是一种后进先出的行为。1.2 函数调用过程栈保存了一个函数调用所需的维护信息:参数、返回地址、局部变量、调用上下文、……每次函数调用都对应着一个栈上的活动记录。调用函数的活动记录位于栈的中部。被调函数的活动记录位于栈的顶部。函数调用栈变化这里返回地址描原创 2017-12-26 20:22:53 · 776 阅读 · 0 评论 -
多维数组和多维指针
1 指向指针的指针指针的本质是变量。指针会占用一定的内存空间。可以定义指针的指针来保存指针变量的地址值。 例如:int main(){ int a = 0; int *p = NULL; int **pp = NULL; pp = &p; *pp = &a; return 0;}2 问题:为什么需要指向指针的指针?指针在本质上也是变量。原创 2017-12-19 15:41:09 · 202 阅读 · 0 评论 -
函数设计原则
函数设计原则(1)函数从意义上应该是一个独立的功能模块。(2)函数名要在一定程度上反映函数的功能。(3)函数参数名要能够体现参数的意义。(4)尽量避免在函数中使用全局变量。 void sc(char *s1, char *s2); void str_opy(char *str_dest, char *str_src);(5)当函数参数不应该在函数体内部被修改时,应加上const声明。(原创 2018-01-02 11:40:05 · 1439 阅读 · 0 评论 -
递归函数分析
1 递归的数学思想递归是一种数学上分而治之的思想。递归需要有边界条件: 当边界条件不满足时,递归继续进行;当边界条件满足时,递归停止。递归将大型复杂问题转换为与原问题相同但规模较小的问题进行处理。2 递归函数函数体内部可以调用自己。递归函数 函数体中存在自我调用的函数。递归函数是递归的数学思想在程序设计中的应用。 递归函数必须有递归出口。函数的无限递归将导致程序栈溢出而崩溃。原创 2018-01-02 10:46:29 · 307 阅读 · 0 评论 -
函数与宏分析
1 函数与宏宏是由预处理器直接替换展开的,编译器不知道宏的存在。函数是由编译器直接编译的实体,调用行为由编译器决定。多次使用宏会导致最终可执行程序的体积增大。函数是跳转执行的,内存中只有一份函数体存在。宏的效率比函数更高,因为是直接展开,无调用开销。函数调用时会创建活动记录,效率不如宏。编程实验:函数与宏#include <stdio.h>#define RESET(p, len)原创 2018-01-01 19:39:46 · 226 阅读 · 0 评论 -
函数参数的秘密
1 函数参数函数参数在本质上与局部变量相同在栈上分配空间。函数参数的初始值是函数调用时的实参值。函数参数的求值顺序依赖于编译器的实现。gcc: 2 1 3(最后一个为k的值) bcc:2 1 3 vc: 1 1 3(跟顺序点有关,假设从第二个参数开始求值,首先从内存中取出k的值为1,此时的++操作并没有进,而是处于悬挂状态,所以第二个参数的值为1。然后对第一个参数进行求值,从内存中取出k原创 2018-01-01 09:43:14 · 229 阅读 · 0 评论 -
函数的意义
1 C语言中的函数函数的由来2 函数的意义模块化程序设计C语言中的模块化3 面向过程的程序设计面向过程是一种以过程为中心的编程思想。首先将复杂的问题分解为一个个容易解决的问题。分解过后的问题可以按照步骤一步步完成。函数是面向过程在C语言中的体现。解决问题的每个步骤可以用函数来实现。4 声明和定义声明的意义在于告诉编译器程序单元的存在。定义则明确指示程序单元的意义。C语言通过exte原创 2017-12-31 11:23:39 · 1717 阅读 · 0 评论 -
动态内存分配
1 动态内存分配的意义C语言中的一切操作都是基于内存的。变量和数组都是内存的别名: 内存分配由编译器在编译期间决定;定义数组的时候必须指定数组长度;数组长度是在编译期就必须确定的。需求:程序运行的过程中,可能需要使用一些额外的内存空间。2 malloc和freemalloc和free用于执行动态内存分配和释放。malloc所分配的是一块连续的内存(不会对内存进行初始化)。malloc原创 2017-12-25 20:31:22 · 335 阅读 · 0 评论 -
内存操作经典问题分析
1 野指针1.1 野指针的概念指针变量中的值是非法的内存地址,进而形成野指针。野指针不是NULL指针,是指向不可用内存地址的指针。NULL指针并无危害,很好判断,也很好调试。C语言中无法判断一个指针所保存的地址是否合法。1.2 野指针的由来局部指针变量没有被初始化。指针所指向的变量在指针之前被销毁(返回局部变量和局部数组)。使用已经释放过的指针。进行了错误的指针运算。进行了错误的原创 2017-12-28 17:24:19 · 186 阅读 · 0 评论 -
指针的本质分析
1 变量的回顾程序中的变量只是一段存储空间的别名,那么是不是必须通过这个别名才能使用这段存储空间?思考: 2 *号的意义在指针声明时,*号表示所声明的变量为指针。在指针使用时,*号表示取指针所指向的内存空间中的值。实例分析:指针使用示例#include <stdio.h>int main(){ int i = 0; int* pI; char* pC; f原创 2017-11-27 22:57:47 · 320 阅读 · 0 评论 -
enum
1 枚举类型的使用方法enum是C语言中的一种自定义类型。enum值是可以根据需要自定义的整形值。第一个定义的enum值默认为0。默认情况下的enum的值是在前一个定义值的基础上加1。enum类型的变量只能取定义时的离散值(enum变量实际上是可以赋值任意的整数值的)。2 枚举类型的特殊意义enum中定义的值是C语言真正意义上的常量。 注意:&只能对变量取地址。在工程中enum多用原创 2017-11-05 17:48:44 · 353 阅读 · 0 评论 -
sizeof
1 sizeof关键字的用法sizeof是编译器的内置指示符。sizeof用于计算类型或变量所占内存大小。sizeof的值在编译期就已经确定。sizeof用于类型:sizeof(type)sizeof用于变量sizeof(var) 或 sizeof var2 为sizeof关键字正名sizeof是C语言的内置关键字而不是函数:在编译过程中所有的sizeof将被具体的数值所替换;程序的原创 2017-11-05 17:54:24 · 169 阅读 · 0 评论 -
typedef
1 typedef的意义typedef用于给一个已经存在的数据类型重命名。typedef本质上不能产生新的类型。typedef重命名的类型:可以在typedef语句之后定义;不能被unsigned和signed修饰。用法:typedef type new_name;实例分析:typedef使用使用示例#include <stdio.h>typedef int Int32;struct _原创 2017-11-05 17:58:31 · 256 阅读 · 0 评论 -
const
1 const只读变量const修饰的变量是只读的,本质还是变量。const修饰的局部变量在栈上分配空间。const修饰的全局变量在全局数据区分配空间。const只在编译期有用,在运行期无用。 注意:const修饰的变量不是真的常量,它只是告诉编译器该变量不能出赋值符号的左边。2 const全局变量的分歧在现代C语言编译器中,修改全局变量将导致程序崩溃。 注意:标准C语言编译器不会将原创 2017-11-01 20:43:52 · 281 阅读 · 0 评论 -
逻辑运算符
1 印象种的逻辑运算符2 有趣的问题实例分析:初探逻辑运算符#include <stdio.h>int main(){ int i = 0; int j = 0; int k = 0; ++i || ++j && ++k; printf("%d\n", i); printf("%d\n", j); printf("%d\n", k); re原创 2017-11-07 22:22:36 · 213 阅读 · 0 评论 -
单引号和双引号
1 单引号和双引号C语言中的单引号用来表示字符字面量。‘a’表示字符字面量。在内存中占1个字节。‘a’+ 1表示‘a’的ASCII码加1,结果为‘b’。C语言中的双引号用来表示字符串字面量。“a”表示字符串字面量。在内存中占2个字节。“a”+ 1表示指针运算,结果指向“a”结束符‘\0’。下面的程序片段合法么? char* p1 = 1 ; char* p2 = '1';原创 2017-11-07 20:34:55 · 143863 阅读 · 0 评论 -
位运算符
1 位运算符分析C语言中的位运算符:位运算符直接对bit位进行操作,其效率最高。2 左移和右移注意点左操作数必须为整数:char和short被隐式转换为int后进行移位操作。右操作数的范围必须为:[0,31]。左移运算符<<将运算数的二进制位左移: 规则:高位丢弃,低位补0。右移运算符>>把运算数的二进制位右移: 规则:高位补符号位,低位丢弃。3 有趣的问题实例分析:位运算符初探#原创 2017-11-08 00:20:19 · 193 阅读 · 0 评论 -
有符号数与无符号数
1 计算机中的符号位数据类型的最高位用于标识数据的符号 最高位为1,表明这个数为负数最高位为0,表明这个数为正数编程实验:有符号数的符号位#include <stdio.h>int main(){ char c = -5; short s = 6; int i = -7; printf("%d\n", ( (c & 0x80) != 0 )); pri原创 2017-07-01 18:42:57 · 706 阅读 · 0 评论 -
浮点数的秘密
1 内存中的浮点数浮点数在内存的存储方式为:符号位、指数、尾数float和double类型的数据在计算机内部的表示法是相同的,但由于所占存储空间的不同,其分别能够表示的数值范围和精度不同。2 浮点数存储示例浮点数的转换 将浮点数转换成二进制用科学计数法表示二进制浮点数计算指数偏移后的值 注意:计算指数时需要加上偏移量,而偏移量的值与类型有关。 示例:对于指数6,偏移后的值如下: f原创 2017-07-02 11:06:41 · 336 阅读 · 0 评论 -
类型转换
1 类型之间的转换C语言终的数据类型可以进行转换 强制类型转换隐式类型转换2 强制类型转换强制类型转换的语法 (Type)var_name;(Type)value;强制类型转换的结果 目标类型能够容纳目标值:结果不变目标类型不能容纳目标值:结果将产生截断注意:不是所有的强制类型转换都能成功,当不能进行强制类型转换时,编译器将产生错误信息实例分析:强制类型转换分析#includ原创 2017-07-03 10:55:22 · 429 阅读 · 0 评论 -
接续符
1 接续符的意义C语言中的接续符()是指示编译器行为的利器。如下的代码是合法的么?#in\clud\e <st\dio.h>in\t m\ain(\){pri\ntf\ (\ "Hello D.T.\n" )\ ;ret\urn 0;}预处理之后的结果如下:int main(){printf ( "Hello D.T.\n"原创 2017-11-07 07:18:09 · 286 阅读 · 0 评论 -
转义字符
1 转义字符的意义C语言种的转义字符()主要用于表示无回显字符,也可以用于表示常规字符。2 转义字符的使用当反斜杠()作为转义字符使用时必须出现在单引号或者双引号之间。实例分析:转义字符使用实例#include <stdio.h>int main(){ char enter = '\n'; char* p = "\141\t\x62"; printf("%s", p);原创 2017-11-07 07:21:46 · 274 阅读 · 0 评论 -
循环语句(while、do...while、for)
1 循环语句分析循环语句的基本工作方式: 通过条件表达式判定是否执行循环体;条件表达式遵循if语句表达式的原则。do、while、for的区别 do语句先执行后判断,循环体至少执行一次;while语句先判断后执行,循环体可能不执行;for语句先判断后执行,相比while更简洁。2 do…while语句的循环方式3 while语句的循环方式4 for语句的循环方式编程实验:三种循环语句原创 2017-10-29 10:33:49 · 603 阅读 · 0 评论 -
void
1 void修饰函数返回值和参数如果函数没有返回值,那么应该将其声明为void;如果函数没有参数,应该声明其参数为void;void修饰函数返回值和参数是为了表示无。 注意:形参为void时代表不接受任何参数,没有写参数意味着可以接受任意多的参数 ,没有写返回值默认返回值为int类型并且值为1。2 )不存在void变量C语言没有定义void究竟是多大内存的别名,没有void的标尺,无法在原创 2017-10-31 21:13:17 · 714 阅读 · 0 评论 -
++和--操作符分析
1 ++,–操作符的本质++和–操作对应两条汇编指令。前置变量自增(减)1取变量值后置取变量值变量自增(减)12 ++,–操作符使用分析一对令人头疼的兄弟:int i = 0; (i++) + (i++) + (i++); (++i) + (++i) + (++i);你觉得这两个表达式的值分别是多少?#include <stdio.h> int main(){ int i =原创 2017-11-08 20:58:08 · 162 阅读 · 0 评论 -
条件编译使用分析
1 基本概念条件编译的行为类似于C语言中的if…else…条件编译是预编译指示命令,用于控制是否编译某段代码。实例分析:条件编译初探// #include <stdio.h>#define C 1int main(){ const char* s; #if( C == 1 ) s = "This is first printf...\n"; #else原创 2017-11-19 17:11:48 · 565 阅读 · 0 评论 -
union
1 C语言中的unionC语言中的union在语法上与struct相似。union只分配最大成员的空间,所有成员共享这个空间。2 union的注意事项union的使用受系统大小端的影响编程实验:编程判断系统的大小端#include <stdio.h>// 1:小端,0:大端int system_mode(){ union SM { int i;原创 2017-11-04 09:07:14 · 308 阅读 · 0 评论