C语言技术类
Coder young
13年毕业逐梦青年来到北京,历任迪普科技(抗D),完美世界(HIDS),当前就职华为(抗D),主攻网络安全DDoS防御
展开
-
gcc编译生成动态链接库,静态库步骤
废话不说,直接干货:首先touch三个文件test.h,test.c,main.ctest.c文件内容:int add(int a, int b){ return a + b;}int sub(int a, int b){ return a - b;}int mul(int a, int b){ return a * b;}int div(int a,原创 2017-03-09 14:28:04 · 2124 阅读 · 0 评论 -
预处理-分节4(#error 预处理,#line 预处理)
#error 预处理指令的作用是,编译程序时,只要遇到#error 就会生成一个编译错误提 示消息,并停止编译。其语法格式为: #error error-message 注意,宏串error-message 不用双引号包围。遇到#error 指令时,错误信息被显示,可能同时还显示编译程序作者预先定义的其他内容。关于系统所支持的error-message 信息,请查找 相关资料,这里原创 2016-10-11 12:58:14 · 394 阅读 · 0 评论 -
预处理-分节3(文件包含)
文件包含是预处理的一个重要功能,它可用来把多个源文件连接成一个源文件进行编 译,结果将生成一个目标文件。C语言提供#include 命令来实现文件包含的操作,它实际是 宏替换的延伸,有两种格式: 格式1:#include 其中,filename 为要包含的文件名称,用尖括号括起来,也称为头文件,表示预处理到 系统规定的路径中去获得这个文件(即C 编译系统所提供的并存放在指定的原创 2016-10-11 12:53:48 · 537 阅读 · 0 评论 -
预处理-分节2(条件编译)
条件编译条件编译的功能使得我们可以按不同的条件去编译不同的程序部分,因而产生不同的目 标代码文件。这对于程序的移植和调试是很有用的。条件编译有三种形式,下面分别介绍: 第一种形式: #ifdef 标识符 程序段1 #else 程序段2 #endif 它的功能是,如果标识符已被#define 命令定义过则对程序段1 进行编译;否则对程序段2 进行编译。如果没有程序段2(它原创 2016-10-11 12:48:52 · 271 阅读 · 0 评论 -
预处理-分节1(宏定义)
数值宏常量 #define 宏定义是个演技非常高超的替身演员,但也会经常耍大牌的,所以我们用它要 慎之又慎。它可以出现在代码的任何地方,从本行宏定义开始,以后的代码就就都认识这 个宏了;也可以把任何东西定义成宏。因为编译器会在预编译的时候用真身替换替身,而 在我们的代码里面却又用常常用替身来帮忙。看例子: #define PI 3.141592654 在此后的代码中你尽可以使用PI原创 2016-10-11 09:21:53 · 706 阅读 · 0 评论 -
第三讲 预处理-引言
往往我说今天上课的内容是预处理时,便有质疑:预处理不就是include 和define 么?这也用得着讲啊?是的,非常值得讨论,即使是include 和define。但是预处理仅限于此吗?远远不止。先看几个个常识性问题: A),预处理是C 语言的一部分吗? B),包含“#”号的都是预处理吗? C),预处理指令后面都不需要加“;”号吗? 不要急着回答,先看看ANSI 标准定义原创 2016-10-10 13:26:58 · 287 阅读 · 0 评论 -
第二讲 符号-(简介及列举)
符号有什么好说的呢?确实,符号可说的内容要少些,但总还是有些可以唠叨地方。‘/’这个符号在C 语言里都用在哪些地方?没有一个人能答完整。 这说明C 语言的基础掌握不牢靠,如果真正掌握了C 语言,你就能很轻易的回答上来。这 个问题就请读者试着回答一下吧。本章不会像关键字一样一个一个深入讨论,只是将容易 出错的地方讨论一下。表(2.1)标准C 语言的基本符号 C 语言的基本符号就有20 多原创 2016-10-10 09:41:43 · 571 阅读 · 0 评论 -
符号-分节8(运算符的优先级下)
一些容易出错的优先级问题 上表中,优先级同为1 的几种运算符如果同时出现,那怎么确定表达式的优先级呢?这是很多初学者迷糊的地方。下表就整理了这些容易出错的情况: 这些容易出错的情况,希望读者好好在编译器上调试调试,这样印象会深一些。一定要多调试,光靠看代码,水平是很难提上来的。调试代码才是最长水平的。 &= 按位与后赋值变量&=表达式 ^= 按位异或后赋值变^=表达原创 2016-10-10 13:23:30 · 331 阅读 · 0 评论 -
符号-分节7(运算符的优先级上)
运算符的优先级表 C 语言的符号众多,由这些符号又组合成了各种各样的运算符。既然是运算符就一定有 其特定的优先级,下表就是C 语言运算符的优先级表: 优先级运算符名称或含义使用形式结合方向说。1 [] 数组下标数组名[常量表达式] 左到右 () 圆括号 (表达式)/函数名(形 参表). 成员选择(对象) 对象.成员名 -> 成员选择(指针) 对象指针->成员名 2原创 2016-10-10 13:21:21 · 390 阅读 · 0 评论 -
符号-分节6(++,--操作符)
这绝对是一对让人头疼的兄弟。先来点简单的: int i = 3; (++i)+(++i)+(++i); 表达式的值为多少?15 吗?16 吗?18 吗?其实对于这种情况,C语言标准并没有作出规定。有点编译器计算出来为18,因为i 经过3 次自加后变为6,然后3 个6 相加得18; 而有的编译器计算出来为16(比如Visual C++6.0),先计算前两个i 的和,这时候i原创 2016-10-10 13:13:03 · 283 阅读 · 0 评论 -
关键字-分节1(auto && register)
auto:它很宽恒大量的,你就当它不存在吧。编译器在默认的缺省情况下,所有变量 都是auto 的。register:这个关键字请求编译器尽可能的将变量存在CPU 内部寄存器中而不是通过内 存寻址访问以提高效率。注意是尽可能,不是绝对。你想想,一个CPU 的寄存器也就那么 几个或几十个,你要是定义了很多很多register 变量,它累死也可能不能全部把这些变量放入寄存器吧,轮也可能轮不到原创 2016-10-09 08:43:54 · 391 阅读 · 0 评论 -
预处理-分节6(#pragma 下)
#pragma code_seg 另一个使用得比较多的pragma 参数是code_seg。格式如: #pragma code_seg( ["section-name"[,"section-class"] ] )它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。#pragma once #pragma once (比较常用) 只要在头文件的最开始加原创 2016-10-11 13:31:13 · 311 阅读 · 0 评论 -
预处理-分节5(#pragma 上)
在所有的预处理指令中,#pragma 指令可能是最复杂的了,它的作用是设定编译器的 状态或者是指示编译器完成一些特定的动作。#pragma 指令对每个编译器给出了一个方法, 在保持与C 和C ++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译 指示是机器或操作系统专有的,且对于每个编译器都是不同的。 其格式一般为: #pragma para 其中para 为原创 2016-10-11 13:00:34 · 299 阅读 · 0 评论 -
指针和数组(第六节 指针数组和数组指针)
初学者总是分不出指针数组与数组指针的区别。其实很好理解:指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。数组指针:首先它是一个指针,它指向一个数组。在32位系统下永远是占4个字节,至于它指向的数组占多少字节,不知道。它是“指向数组的指针”的简称。下面到底哪个是数组指针,哪个是指针数组呢:A),int*p1[10];B),原创 2016-12-08 19:04:46 · 340 阅读 · 0 评论 -
指针和数组(第五节 定义与声明)
文件1中定义如下:chara[100];文件2中声明如下:externchar*a; (关于extern的用法,以及定义和声明的区别,请复习第一章)这里,文件1中定义了数组a,文件2中声明它为指针。这有什么问题吗?平时不是总说数组与指针相似,甚至可以通用吗?但是,很不幸,这是错误的。通过上面的分析我们也能明白一些,但是“革命尚未成功,同志仍需努力”。你或许还记得我上面说过的话:数组就是数组原创 2016-12-08 18:59:37 · 381 阅读 · 0 评论 -
指针和数组(第四节 指针与数组之间的恩恩怨怨)
很多初学者弄不清指针和数组到底有什么样的关系。我现在就告诉你:他们之间没有任何关系!只是他们经常穿着相似的衣服来逗你玩罢了。指针就是指针,指针变量在32位系统下,永远占4个byte,其值为某一个内存的地址。指针可以指向任何地方,但是不是任何地方你都能通过这个指针变量访问到。数组就是数组,其大小与元素的类型和个数有关。定义数组时必须指定其元素的类型和个数。数组可以存任何类型的数据,但不能存函原创 2016-12-08 18:54:34 · 346 阅读 · 0 评论 -
指针和数组(数组名a作为左值和右值的区别)
简单而言,出现在赋值符“=”右边的就是右值,出现在赋值符“=”左边的就是左值。比如,x=y。左值:在这个上下文环境中,编译器认为x的含义是x所代表的地址。这个地址只有编译器知道,在编译的时候确定,编译器在一个特定的区域保存这个地址,我们完全不必考虑这个地址保存在哪里。右值:在这个上下文环境中,编译器认为y的含义是y所代表的地址里面的内容。这个内容是什么,只有到运行时才知道。C语言引入一原创 2016-12-08 18:40:47 · 1206 阅读 · 0 评论 -
指针和数组(第二节 数组的内存布局 )
先看下面的例子:inta[5];所有人都明白这里定义了一个数组,其包含了5个int型的数据。我们可以用a[0],a[1]等来访问数组里面的每一个元素,那么这些元素的名字就是a[0],a[1]…吗?当我们定义一个数组a时,编译器根据指定的元素个数和元素的类型分配确定大小(元素类型大小*元素个数)的一块内存,并把这块内存的名字命名为a。名字a一旦与这块内存匹配就不能被改变。a[0],a[1]等原创 2016-12-08 18:38:45 · 286 阅读 · 0 评论 -
指针和数组(分节1-指针的内存布局)
指针是C语言和C++语言的精华如果未能很好地掌握指针,那 C/C++也基本等于没学。可惜,对于刚毕业的计算机系的学生,几乎没有人真正完全掌握了指针和数组、以及内存管理,那么什么是指针,什么是数组。数组和指针之间有什么样的关系?int*p;大家都知道这里定义了一个指针 p。但是 p到底是什么东西呢?还记得第一章里说过,“任何一种数据类型我们都可以把它当一个模子”吗?p,毫无疑原创 2016-11-15 09:51:10 · 310 阅读 · 0 评论 -
预处理-分节8(#运算符)
#也是预处理?是的,你可以这么认为。那怎么用它呢?别急,先看下面例子#defineSQR(x) printf("Thesquareof x is%d.\n",((x)*(x)));如果这样使用宏: SQR(8);则输出为: Thesquareof x is 64.注意到没有,引号中的字符 x被当作普通文本来处理,而不是被当作一个可以被替换的语言符号。假如你确实希望在字符原创 2016-11-15 09:34:25 · 311 阅读 · 0 评论 -
预处理-分节7(如何避免内存对齐的影响)
那么,能不能既达到提高性能的目的,又能节约一点空间呢?有一点小技巧可以使用。 比如我们可以将上面的结构改成: struct TestStruct2 { char c1; char c2; short s; int i; }; 这样一来,每个成员都对齐在其自然边界上,从而避免了编译器自动对齐。在这个例 子中,sizeof(TestStruct2)的值为8。这个技巧有一个重要的原创 2016-10-11 13:36:42 · 582 阅读 · 0 评论 -
预处理-分节6(#pragma 为什么会有内存对齐)
单字,双字,和四字在自然边界上不需要在内存中对齐。(对字,双字,和四字来说,自 然边界分别是偶数地址,可以被4 整除的地址,和可以被8 整除的地址。)无论如何,为了 提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为 了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。 一个字或双字操作数跨越了4 字节边界,或者一个四字操作原创 2016-10-11 13:35:35 · 381 阅读 · 0 评论 -
符号-分节5(花括号)
花括号每个人都见过,很简单吧。但曾经有一个人问过我如下问题: char a[10] = {“abcde”}; 他不理解为什么这个表达式正确。我让他继续改一下这个例子: char a[10] { = “abcde”}; 问他这样行不行。那读者以为呢?为什么? 花括号的作用是什么呢?我们平时写函数,if、while、for、switch 语句等都用到了它, 但有时又省略掉了它。简单原创 2016-10-10 13:08:57 · 1119 阅读 · 0 评论 -
符号-分节4(逻辑运算符,位运算及左右移位运算)
逻辑运算符||和&&是我们经常用到的逻辑运算符,与按位运算符|和&是两码事。下一节会介绍按位 运算符。虽然简单,但毕竟容易犯错。看例子: int i=0; int j=0;if((++i>0)||(++j>0)) { //打印出i 和j 的值。 } 结果:i=1;j=0。 不要惊讶。逻辑运算符||两边的条件只要有一个为真,其结果就为真;只要有一个结果 为假,其结果就为假原创 2016-10-10 13:01:18 · 522 阅读 · 0 评论 -
关键字-分节9(void和retuan)
void 不能代表一个真实的变量void 不能代表一个真实的变量。 因为定义变量时必须分配内存空间,定义void 类型变量,编译器到底分配多大的内存呢。 下面代码都企图让void 代表一个真实的变量,因此都是错误的代码: void a; //错误function(void a); //错误 void 体现了一种抽象,这个世界上的变量都是“有类型”的,譬如一个人不是男人就是女 人原创 2016-10-10 08:55:39 · 271 阅读 · 0 评论 -
关键字-分节8(do、while、for,break 与continue,goto)
C 语言中循环语句有三种:while 循环、do-while 循环、for 循环。 while 循环:先判断while 后面括号里的值,如果为真则执行其后面的代码;否则不执 行。while(1)表示死循环。break 与continue 的区别 break 关键字很重要,表示终止本层循环。现在这个例子只有一层循环,当代码执行到 break 时,循环便终止。 如果把break 换成c原创 2016-10-09 18:43:50 · 302 阅读 · 0 评论 -
关键字-分节7(switch、case)
switch、case 组合 既然有了if、else 组合为什么还需要switch、case 组合呢?if、else 一般表示两个分支或是嵌套表示少量的分支,但如果分支很多的话……还是用 switch、case 组合吧。 case 关键字后面的值有什么要求吗? 好,再问问:真的就这么简单吗?看看下面的问题: Value1 的值为0.1 行吗?-0.1 呢?-1 呢?0.1+原创 2016-10-09 18:39:31 · 353 阅读 · 0 评论 -
关键字-分节6(if、else 组合,bool,float及指针)
if、else 组合if 语句很简单吧。嗯,的确很简单。那我们就简单的看下面几个简单的问题:bool 变量与“零值”进行比较 bool 变量与“零值”进行比较的if 语句怎么写? bool bTestFlag = FALSE;//想想为什么一般初始化为FALSE 比较好? A), if(bTestFlag == 0); if(bTestFlag == 1);B), if(b原创 2016-10-09 18:36:32 · 350 阅读 · 0 评论 -
关键字-分节5(signed、unsigned)
signed、unsigned 关键字我们知道计算机底层只认识0、1.任何数据到了底层都会变计算转换成0、1.那负数怎么 存储呢?肯定这个“-”号是无法存入内存的,怎么办?很好办,做个标记。把基本数据类 型的最高位腾出来,用来存符号,同时约定如下:最高位如果是1,表明这个数是负数,其 值为除最高位以外的剩余位的值添上这个“-”号;如果最高位是0,表明这个数是正数, 其值为除最高位以外的剩余原创 2016-10-09 18:33:44 · 324 阅读 · 0 评论 -
关键字-分节4(sizeof)
常年被人误认为函数sizeofsizeof 是关键字不是函数,其实就算不知道它是否为32 个关键字之一时,我们也可以 借助编译器确定它的身份。看下面的例子: int i=0;A),sizeof(int); B),sizeof(i); C),sizeof int; D),sizeof i; 毫无疑问,32 位系统下A),B)的值为4。那C)的呢?D)的呢?在32 位系统下,通过Vis原创 2016-10-09 18:32:45 · 298 阅读 · 0 评论 -
关键字分节3(基本数据类型-short、int、long、char、float、double)
基本数据类型----short、int、long、char、float、double基本类型 构造类型 指针类型 空类型void 数值类型 字符类型char 枚举类型enum 整 型 浮点型 单精度型float 双精度型double 短整型short 长整型long 整型int 数组 结构体struct 共用体union。short、int、long、char、float、doub原创 2016-10-09 18:32:07 · 1665 阅读 · 0 评论 -
关键字-分节2(static)
static:不要误以为关键字static 很安静,其实它一点也不安静。这个关键字在C 语言里主要有 两个作用,C++对它进行了扩展。第一个作用:修饰变量。变量又分为局部和全局变量,但它们都存在内存的静态区。 静态全局变量,作用域仅限于变量被定义的文件中,其他文件即使用extern 声明也没法 使用他。准确地说作用域是从定义之处开始,到文件结尾处结束,在定义之处前面的那些 代码行也不能使用原创 2016-10-09 18:31:06 · 264 阅读 · 0 评论 -
第一讲 关键字-列举
sizeof是什么?哦,sizeof()不是函数吗?,是的,它并不是函数,是关键字。那么c语言有多少个关键字,是32个,你都了解吗?auto 声明自动变量,缺省时编译器一般默认为auto int 声明整型变量 double 声明双精度变量 long 声明长整型变量 char 声明字符型变量 float 声明浮点型变量 short 声明短整型变量 signed原创 2016-10-08 21:33:04 · 567 阅读 · 0 评论 -
关键字-分节10(const)
const 关键字也许该被替换为readolnyconst 是constant 的缩写,是恒定不变的意思,也翻译为常量、常数等。很不幸,正是 因为这一点,很多人都认为被const 修饰的值是常量。这是不精确的,精确的说应该是只读 的变量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。或许当初 这个关键字应该被替换为readonly。那么这个关键字有什么用处和意义呢?原创 2016-10-10 09:04:18 · 226 阅读 · 0 评论 -
关键字-分节11(volatile)
最易变的关键字----volatilevolatile 是易变的、不稳定的意思。很多人根本就没见过这个关键字,不知道它的存在。 也有很多程序员知道它的存在,但从来没用过它。我对它有种“杨家有女初长成,养在深闺 人未识” 的感觉。volatile 关键字和const 一样是一种类型修饰符,用它修饰的变量表示可以被某些编译器 未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字原创 2016-10-10 09:13:22 · 234 阅读 · 0 评论 -
关键字-分节12(extern)
extern,外面的、外来的意思。那它有什么作用呢?举个例子:假设你在大街上看到 一个黑皮肤绿眼睛红头发的美女(外星人?)或者帅哥。你的第一反应就是这人不是国产 的。extern 就相当于他们的这些区别于中国人的特性。extern 可以置于变量或者函数前,以 标示变量或者函数的定义在别的文件中,下面的代码用到的这些变量或函数是外来的,不 是本文件定义的,提示编译器遇到此变量和函数时在其他模块中原创 2016-10-10 09:16:47 · 347 阅读 · 0 评论 -
符号-分节3(单引号和双引号)
单引号、双引号我们知道双引号引起来的都是字符串常量,单引号引起来的都是字符常量。但初学者 还是容易弄错这两点。比如:‘a’和“a”完全不一样,在内存里前者占1 个byte,后者占2 个byte。关于字符串常量在指针与数组那章将有更多的讨论。 这两个列子还好理解,再看看这三个: 1,‘1‘,“1”。 第一个是整形常数,32 位系统下占4 个byte; 第二个是字符常量,占1 个byt原创 2016-10-10 12:58:06 · 519 阅读 · 0 评论 -
符号-分节2(接续符和转译符)
接续符和转义符C 语言里以反斜杠(\)表示断行。编译器会将反斜杠剔除掉,跟在反斜杠后面的字符 自动接续到前一行。但是注意:反斜杠之后不能有空格,反斜杠的下一行之前也不能有空 格。当然你可以测试一下加了空格之后的效果。我们看看下面的例子: //这是一条合法的\ 单行注释 /\ /这是一条合法的单行注释 #def\ ine MAC\ RO 这是一条合法的\ 宏定原创 2016-10-10 12:53:57 · 505 阅读 · 0 评论 -
符号-分节1(注释符号)
几个似非而是的注释问题 C 语言的注释可以出现在C 语言代码的任何地方。这句话对不对?这是我当学生时我 老师问的一个问题。我当时回答是不对。好,那我们就看看下面的例子: A),int/*...*/i;B),char* s="abcdefgh //hijklmn"; C), //Is it a \ valid comment? D), in/*…*/t i; 我_______们知道C原创 2016-10-10 09:46:10 · 864 阅读 · 0 评论 -
关键字-分节18(typedef)
有这样一个笑话:一个猎人在河边抓捕一条蛇,蛇逃进了水里。过一会,一个乌龟爬到岸边。猎人一把抓住这个乌龟,大声的说道:小样,别你为你穿了个马甲我就不认识你 了! typedef 关键字是个伟大的缝纫师,擅长做马甲,任何东西穿上这个马甲就立马变样。 它可以把狼变成一头羊,也能把羊变成一头狼。甚至还可以把长着翅膀的鸟人变成天使, 同样也能把美丽的天使变成鸟人。所以,你千万不要得罪它,一定要掌握它的脾原创 2016-10-10 09:31:54 · 394 阅读 · 0 评论