c语言深度剖析
小虾米_2018
专注于C、C++、嵌入式系统、网络、驱动编程~
展开
-
c语言深度剖析(1)—基本数据类型
1.数据类型1.1什么是数据类型数据类型可以理解为固定内存大小的别名 数据类型是创建变量的模子1.2数据类型的本质2.变量的本质变量是一段实际连续存储空间的别名 程序中通过变量来申请并命名存储空间 通过变量的名字可以使用存储空间3.编程实验类型与变量的关系#include <stdio.h>#include <stdlib.h...原创 2019-08-30 20:16:28 · 1503 阅读 · 0 评论 -
c语言深度剖析(2)—有符号与无符号
1.数据类型1.1 计算机中的符号位有符号编码规则:数据的最高位用于标识数据的符号 最高位为1,表示这个数为负数 最高位为0,表示这个数为正数 无符号编码规则:数据的最高位不代表符号位 计算机不知道数据的正负,看人怎么看待 1.2 编程实验有符号数的符号位#include <stdio.h>int main(){ char c = -5...原创 2019-08-30 20:16:37 · 2079 阅读 · 0 评论 -
c语言深度剖析(3)—浮点数的秘密
1.内存中的浮点数——存储方式:符号位、指数、尾数的符号float与double类型的数据在计算机内部的表示法是相同的,但由于所占存储空间不同,分别能够表示的数据值范围和精度不同。 解释:对于5.14 *10^11 : 14为尾数,11为指数,10为基2.浮点数的存储示例2.1浮点数的转换步骤将浮点数转换成二进制 用科学计数法表示二进制浮点数,十进制的整数部分转换为二...原创 2019-08-06 14:22:39 · 354 阅读 · 0 评论 -
c语言深度剖析(4)—类型转换
1. C语言中的类型之间的转换:强制类型转换和隐式类型的转换#include<stdio.h>int main(){ long l = 800; int i = (int)l; // 强制类型转换 short s = 800; int k = s; // 隐式类型转换,no error,no warning return 0;}...原创 2019-08-06 14:22:47 · 204 阅读 · 0 评论 -
c语言深度剖析(5)—变量属性auto、register、static、extern
1.C语言的变量属性C语言中的变量可以有自己的属性 在定义变量的时候可以加上“属性”关键字 “属性”关键字指明变量的特有意义。语法:propertytypevar_name;如:auto char i; register int j; static long k; extern double m;2. auto关键字auto即C语言中局部变量的默认属...原创 2019-08-06 14:22:54 · 368 阅读 · 0 评论 -
c语言深度剖析(6)—分之语句
1. if语句if语句用于根据条件选择执行语句 else不能独立存在且总是与它之前最近的if相匹配 else语句后可以接连其他if语句if语句中零值比较的注意点 ①bool型变量直接出现于条件中,不要进行比较 ②变量和0值比较时,0值应该出现在比较符号左边 ③float型变量不能直接进行0值比较,需要定义精度 2.switch语句分析switch语句对应单个条件...原创 2019-08-06 14:23:06 · 191 阅读 · 0 评论 -
c语言深度剖析(7)—循环语句
1.循环语句分析循环语句的基本工作方式 ①通过条件表达式判定是否执行循环体 ②条件表达式遵循if语句表达式的原则 do、while、for的区别 ①do语句先执行后判断,循环体至少执行一次 ②while语句先判断后执行,循环体可能不被执行 ③for语句先判断后执行,相比while更简洁 2.循环的回顾do…while语句的循环方式while语句的循环方式...原创 2019-08-06 14:23:13 · 244 阅读 · 0 评论 -
c语言深度剖析(8)—循环语句goto和void分析
1.遭人遗弃的goto高手潜规则:禁用goto 项目经验:程序质量与goto的出现次数成反比 最后的判决:将goto打入冷宫2.编程实验goto副作用分析#include <stdio.h>#include <stdlib.h>#include <malloc.h>void func(int n){ int *p = NULL;...原创 2019-08-06 14:23:20 · 251 阅读 · 0 评论 -
c语言深度剖析(9)—const和volatile分析
1. const只读变量——(注意不是真正常量,只是告诉编译器不能出现在赋值号左边!)const修饰的变量是只读的,本质还是变量 const修饰的局部变量在栈上分配空间 const修饰的全局变量在全局数据区分配空间(vc、gcc会将其放入常量区,bcc放入全局数据区) const只在编译期有用(只能出现在赋值符号左边),在运行期无用#include <stdio.h>...原创 2019-08-06 14:23:27 · 245 阅读 · 0 评论 -
c语言深度剖析(10)—struct和union分析
1.struct的小秘密C语言中的struct可以看作变量的集合 struct的问题:空结构体占用多大内存?#include <stdio.h>struct TS{};int main(){ struct TS t1; struct TS t2; // VC、BCC下定义空结构体编译器直接报错,gcc下空结构体大小为0 ...原创 2019-08-08 10:00:11 · 263 阅读 · 0 评论 -
c语言深度剖析(11)—enum、sizeof、typedef 分析
1. enum枚举类型1.1使用方法enum是C语言中的一种自定义类型 enum值是可以根据需要自定义的的整型值 第一个定义的enum值默认为0 默认情况下的enum值是在前一个定义值的基础上加1 enum类型的变量只能取定义时的离散值enum Color{ GREEN, // GREEN==0; RED= 2, // 自定义RED==2;...原创 2019-08-08 10:00:27 · 300 阅读 · 0 评论 -
c语言深度剖析(12)—注释符号
1.似是而非的问题下面的注释是正确的吗?#include<stdio.h>int main(){ int/**/i; //合法int i; char* s = "abcdefg //ijklmn"; //合法引号内的双斜杠 //Is it a \ valid c...原创 2019-08-08 10:00:34 · 481 阅读 · 0 评论 -
c语言深度剖析(13)—接续符和转义符
1.接续符的意义C语言中的接续符(\)是指示编译器行为的利器// 使用接续符的例子#in\clud\e <st\dio.h>in\t m\ain(\){pri\ntf\ (\ "Hello World!\n" )\ ; ret\urn 0;}// 剔除接续符后的原码#include <stdio...原创 2019-08-08 10:00:40 · 648 阅读 · 0 评论 -
c语言深度剖析(14)—单引号和双引号
1.单引号和双引号C语言中单引号用来表示字符字面量(是个数值) C语言中双引号用来表示字符串字面量(是个指针) 'a'表示字符字面量(97),在内存中占用1个字节,'a'+1表示'a'的ASCII码加1,即'b' "a"表示字符串字面量(是个指针),在内存中占2个字了,"a"+1表示指针运算,指向"a"的结束符"\0" 下面的程序片段合法吗?char *pl = 1;c...原创 2019-08-08 10:01:02 · 1231 阅读 · 0 评论 -
c语言深度剖析(15)—逻辑运算符分析
1.有趣问题逻辑运算符&&,||和!真的很简单吗?#include <stdio.h>int main(){ int i = 0; int j = 0; int k = 0; // 等价于(true && ++i) ||(++j && ++k)可见整个表达式为或运算,从左向右进行...原创 2019-08-08 10:01:09 · 638 阅读 · 0 评论 -
c语言深度剖析(16)—位运算符分析
1.C语言中的位运算符位运算符直接对bit位进行操作,其效率最高2.左移和右移注意点左操作数必须为整型类型:char和short被隐式转换为int后进行移位操作 右操作数的范围必须为:[0,31],其他值属未定义行为,不同编译器处理不同。 左移运算符<< 将运算数的二进制位左移:规则为高位丢弃,低位补0 右移运算符>> 把运算数的二进制位右移:规...原创 2019-08-08 10:01:14 · 808 阅读 · 0 评论 -
c语言深度剖析(17)—++和--操作符分析
1. ++和—操作符对应的两条汇编指令前置++或--:变量自增(减)1,然后取变量值 后置++或--:取变量值,然后变量自增(减)12.++,-- 操作符使用分析一对令人头疼的兄弟nti=0;(i++)+(i++)+(i++);(++i)+(++i)+(++i);#include <stdio.h>in...原创 2019-08-08 10:27:51 · 308 阅读 · 0 评论 -
c语言深度剖析(18)—三目运算符和逗号表达式
1.三目运算符三目运算符(a?b:c)可以作为逻辑运算的载体 规则:当a的值为真时,返回变量b的值(而不是变量本身);否则返回c的值。(c++中返回变量本身) 三目运算符(a?b:c)的返回类型 通过隐式类型转换规则返回b或c中较高的类型 当b和c不能隐式转换到同一类型时将编译出错 2.编程实验三目运算符初探#include <stdio.h>#inclu...原创 2019-08-08 11:19:26 · 491 阅读 · 0 评论 -
c语言深度剖析(19)—编译过程简介
1.初始编译器2.预编译:指令示例——gcc –E file.c –o file.i处理所有的注释,以空格代替 将所有的#define删除,并且展开所有的宏定义 处理条件编译指令#if、#ifdef、#elif、#else、#endif 处理#include,展开被包含的文件 保留编译器需要使用的#pragma指令3.编译:指令示例——gcc –S file.i –o ...原创 2019-08-08 14:22:28 · 219 阅读 · 0 评论 -
c语言深度剖析(20)—链接过程简介
1.链接器的意义每个C语言源文件被编译后生成目标文件,这些目标文件最终要被链接在一起生成可执行文件 链接器的主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接2.静态链接由链接器在链接时将库的内容直接加入到可执行程序中Linux下静态库的创建和使用 编译静态库源码: gcc -c lib.c -o lib.o 生成静态库文件: ar -...原创 2019-08-08 15:10:07 · 293 阅读 · 0 评论 -
c语言深度剖析(21)—宏定义的使用与分析
0.对于宏的第一印象:可以定义一个常量,如:#define PI 3.14159 可以定义一个代码块,将宏作为函数使用,如:# include <stdio.h>// 此处将交换两个变量的函数用宏来定义#define SWAP(a, b) \{ \ int temp = a; \ a =...原创 2019-08-08 17:08:34 · 303 阅读 · 0 评论 -
c语言深度剖析(22)—条件编译使用分析
1.基本概念条件编译的行为类似于C语言中的if…else…; 条件编译是预编译指示命令,用于控制是否编译某段代码; 可以利用预处理器调整代码、删除代码的操作。2.编程实验条件编译初探//#include<stdio.h>#define C 1int main(){ const char* s;#if(1 == C) s = "this is fir...原创 2019-08-08 23:27:30 · 158 阅读 · 0 评论 -
c语言深度剖析(23)—error和#line使用分析
1.#error的用法#error用于生成一个编译错误消息 用法:#error message,其中message不需要用双引号包围 #error编译指示字用于自定义程序员特有的编译错误消息,类似的,#warning用于生成编译警告 #error是一种预编译器指示字 #error可用于提示编译条件是否满足 编译过程中的任意错误信息意味着无法生成最终的可执行程序。2.编程实验...原创 2019-08-09 09:42:01 · 265 阅读 · 0 评论 -
c语言深度剖析(24)—#pragma使用分析、内存对齐
1.#pragma简介#pragma用于指示编译器完成一些特定的动作 #pragma所定义的很多指示字是编译器特有的 #pragma在不同的编译器间是不可移植的 预处理器将忽略它不认识的#pragma指令 不同的编译器可能以不同的方式解释同—条#pragma指令 一般用法:#pragma parameter,注:不同的parameter参数语法和意义各不相同2...原创 2019-08-09 15:43:16 · 389 阅读 · 0 评论 -
c语言深度剖析(25)—#和##操作符使用分析
1.#运算符#运算符用于在预处理期将宏参数转换为字符串 #的转换作用是在预处理期完成的,因此只在宏定义中有效 编译器不知道#的转换作用 用法 :#define STRING(x)#xprintf("%s\n", STRING(Hello World!));#运算符的基本用法#include<stdio.h>#defineSTRING(...原创 2019-08-09 22:29:09 · 178 阅读 · 0 评论 -
c语言深度剖析(26)—指针的本质分析
程序中的变量只是一段存储空间的别名,那么是不是必须通过这个别名才能使用这段存储空间? 问题:程序中的变量只是一段存储空间的别名,那么是不是必须通过这个别名才能使用这段存储空间? 问题:是不是只能通过变量使用存储空间?#include<stdio.h>int main(){ int i = 5; int *p = &i; printf("i = %d, p =...原创 2019-08-11 22:53:40 · 225 阅读 · 0 评论 -
c语言深度剖析(27)—数组的本质分析
1.数组的基本概念数组是相同类型的变量的有序集合数组当中的元素没有名字,我们只能通过数组名和下标来访问数组中的元素。数组名a代表的是这5个存储空间的集合。代表的是这一段内存。 数组在—片连续的内存空间中存储元素,数组元素的个数可以显示或隐式指定#include <stdio.h>int main(){ int a[5] = { 1, 2 }; // 显...原创 2019-08-11 22:53:51 · 432 阅读 · 0 评论 -
c语言深度剖析(28)—指针和数组分析(上)
1. 数组的本质数组是一段连续的内存空间; 数组的空间大小为sizeof(array_type)*array_size; 数组名可看做指向数组第一个元素的指针常量。 问题: a + 1的意义是什么?结果是什么? 指针运算的意义是什么?结果是什么?#include<stdio.h>int main(){ int a[5] = {1, 2}; ...原创 2019-08-12 10:26:06 · 192 阅读 · 0 评论 -
c语言深度剖析(29)—指针和数组分析(下)
问题:数组名可以当作指针常量使用,那么指针是否也可以当作数组来使用呢?通过下标的形式访问数组中的元素int main(){ int a[5] = {0}; a[1] = 3; a[2] = 5; return 0;}通过指针的形式访问数组中的元素int main(){ int a[5] = {0}; *(a + 1) = 3;...原创 2019-08-12 11:53:27 · 241 阅读 · 0 评论 -
c语言深度剖析(30)—C语言中的字符串
1.字符串的概念字符串是有序字符的集合 字符串是程序中的基本元素之一 C语言中没有字符串的概念 C语言中通过特殊的字符数组模拟字符串 C语言中的字符串是以'\0'结尾的字符数组 2.字符数组与字符串在C语言中,双引号引用的单个或多个字符是一种特殊的字面量 存储于程序的全局只读存储区 本质为字符数组,编译器自动在结尾加上'\0'字符 char s...原创 2019-08-12 15:08:39 · 220 阅读 · 0 评论 -
c语言深度剖析(31)—字符串典型问题分析
1.典型问题一下面的程序输出什么?为什么?#include <stdio.h>int main(){ char buf[10] = { 0 }; char src[] = "hello %s"; snprintf(buf, sizeof(buf), src); printf("buf = %s\n", buf); return 0;}运行结果: 输...原创 2019-08-12 16:30:29 · 244 阅读 · 0 评论 -
c语言深度剖析(32)—数组指针和指针数组分析
1. 思考题:下面的声明合法吗?int array[5];int matrix[3][3];int *pa = array;int *pm = matrix;合法,第一个为标准数组的定义,第二个为二维数组的定义,第三个为指向数组的指针,第四个为指向二维数组的指针。 问题: array代表数组首元素的地址,那么matrix代表什么? array和&array的地址值相...原创 2019-09-01 09:58:49 · 404 阅读 · 0 评论 -
c语言深度剖析(33)—main函数与命令行参数
1.main函数的概念C语言中main函数称之为主函数,一个C语言程序是从main函数开始执行。 main函数定义的标准形式:经实验可知都正确2. main函数的本质main函数是操作系统调用的函数; 操作系统总是将main函数作为应用程序的开始 操作系统将main函数的返回值作为程序的退出状态 思考:为什么C编译器支持那么多不同的main函数原型? 操作系统是...原创 2019-08-13 19:51:23 · 258 阅读 · 0 评论 -
c语言深度剖析(34)—多维数组和多级指针
1.指向指针的指针指针的本质是变量 指针会占用—定的内存空间 可以定义指向指针的指针来保存指针变量的地址值int main(){ int i = 0; int *p = NULL; // 定义指针变量p int **pp = NULL; // 定义二级指针变量pp pp = &p; // 二级指针变量pp保存指针变量p的地址 *...原创 2019-08-13 21:24:07 · 322 阅读 · 0 评论 -
c语言深度剖析(35)—数组参数和指针参数分析
1.思考为什么C语言中的数组参数会退化为指针?2.退化的意义C语言中只会以值拷贝的方式传递参数 当向函数传递数组时: 将整个数组拷贝—份传入函数(X) 将数组名看做指针常量传数组首元素地址 ( ✔ ) C语言以高效作为最初设计目标: 参数传递的时候如果拷贝整个数组执行效率将大大下降 参数位于栈上,太大的数组拷贝将导致栈溢出 3.二维数组参数...原创 2019-08-13 22:04:05 · 248 阅读 · 0 评论 -
c语言深度剖析(36)—函数与指针分析
1.函数类型C语言中的函数有自己特定的类型 函数的类型由返回值,参数类型和参数个数共同决定 int add(int i, int j) 的类型为int(int, int) C语言中通过typedef为函数类型重命名 typedef type name(parameter list) 2.函数指针函数指针用于指向—个函数 函数名是执行函数体的入口地址 可...原创 2019-08-14 11:07:49 · 232 阅读 · 0 评论 -
c语言深度剖析(37)—指针阅读技巧分析
1.指针阅读技巧解析右左法则 (实在看不懂看这个) 从最里层的圆括号中未定义的标示符看起 首先往右看,再往左看 遇到圆括号或方括号时可以确定部分类型,并调转方向 重复2, 3步骤,直到阅读结束 示例:#include <stdio.h>int main(){ int (*p)(int) int (*p1)(int*, in...原创 2019-08-14 11:29:06 · 299 阅读 · 0 评论 -
c语言深度剖析(38)—C语言中的动态内存分配
1.动态内存分配的意义C语言中的—切操作都是基于内存的 变量和数组都是内存的别名 内存分配由编译器在编译期间决定 定义数组的时候必须指定数组长度 数组长度是在编译期就必须确定的 需求:程序运行的过程中,可能需要使用—些额外的内存空间。2.malloc和freemalloc和free用于执行动态内存分配和释放malloc所分配的是—块连续的内存(虚拟内存...原创 2019-08-14 23:26:26 · 223 阅读 · 0 评论