C语言
文章平均质量分 67
zegeyzz
这个作者很懒,什么都没留下…
展开
-
enum和typedef分析
enum是一种自定义类型,真真正正的常量enum默认常量在前一个值的基础上依次加1enum类型的变量只能取定义时的离散值,只能是int型enum类型变量只能取值为花括号内的任何一个值enum color{ GREEN, RED = 2, BLUE};enum变量类型还可以给其中的常量符号赋值,如果不赋值则会从被赋初值的那个常量开始依次加1,如原创 2013-07-16 21:25:04 · 551 阅读 · 0 评论 -
函数与指针分析
函数类型C语言中的函数有自己特定的类型函数类型由返回值,参数类型,参数个数共同决定参数类型和参数个数隐含了另一个条件:参数顺序例:int add(float i, char j) 的类型为int(int, int),其返回值类型是int,有两个参数,第一个参数float,第二个参数char int ff(double e, int i); //ff函数原创 2013-07-20 10:26:31 · 519 阅读 · 0 评论 -
程序中的栈、堆和静态存储区
一般来说,我们可以简单的理解为内存分为三个部分:静态区,栈,堆。很多书没有把把堆和栈解释清楚,导致初学者总是分不清楚。其实堆栈就是栈,而不是堆。堆的英文是heap ;栈的英文是stack,也翻译为堆栈。堆和栈都有自己的特性。程序中的栈栈是现代计算机程序里最重要的概念之一栈在程序中用于维护函数调用的上下文,没有栈就没有函数,没有局部变量后进先出栈保存了一个函数调用原创 2013-07-20 12:16:52 · 557 阅读 · 0 评论 -
野指针和内存操作分析
初始也指针野指针通常是因为指针变量中保存饿值不是一个合法的内存地址而造成的合法的内存地址:1.堆空间申请的动态空间 2.栈空间上的局部变量所占用的空间野指针不是NULL指针,是指不可用内存的指针NULL指针不容易出错,因为if语句很好判断一个指针是不是NULLC语言没有任何手段可以判断一个指针收费为野指针!野指针的由来1.局部指针没有被初始化struct St原创 2013-07-20 18:07:48 · 519 阅读 · 0 评论 -
程序的内存布局
代码在可执行程序中的对应关系如何执行编译出来的a.out文件呢?命令行敲如a.out文件,之后就可运行了。操作系统怎么知道这是一个可执行程序的呢?操作系统在接到./a.out这个命令后回去读文件头,读文件头看一下这个文件头里面对应的是不是可执行程序的信息。如果是的话,操作系统就知道这是一个可执行程序,操作系统就要为这个可执行程序分配一些内存空间来给其运行。这个内存空间很有可能一部分当做原创 2013-07-20 15:54:59 · 554 阅读 · 0 评论 -
认清函数的真面目
函数的由来与好处——以下摘自陈正冲《C语言深度剖析》其实在汇编语言阶段,函数这个概念还是比较模糊的。汇编语言的代码往往就是从入口开始一条一条执行,直到遇到跳转指令(比如ARM 指令B 、BL 、BX 、BLX 之类)然后才跳转到目的指令处执行。这个时候所有的代码仅仅是按其将要执行的顺序排列而已。后来人们发现这样写代码非常费劲,容易出错,也不方便。于是想出一个办法,把一些功能相对原创 2013-07-20 21:49:56 · 541 阅读 · 0 评论 -
可变参数分析
可变参数C语言中可以定义参数可变的函数,可以增加可以减少,如:printf()参数可变函数的实现依赖于stdarg.h头文件va_list 变量与 va_start,va_end 和 va_arg 配合使用能够访问参数值例1:#include #include stdarg.h>float average(int n, ...){ va_list args;原创 2013-07-20 22:11:39 · 448 阅读 · 0 评论 -
动态内存分配
为什么使用动态内存分配?C语言中的一切操作都是基于内存的变量和数组都是内存的别名,如何分配这些内存由编译器在编译期间决定.定义数组的时候必须指定数组唱的.而数组长度是在编译期就必须决定的需求:程序运行的过程中,可能需要使用一些额外的内存空间malloc和freemalloc和free用于执行动态内存分配和释放malloc所分配的是一块连续的内存,以字原创 2013-07-20 11:21:53 · 562 阅读 · 0 评论 -
指针数组和数组指针分析
int指的是数组元素的类型,而不是数组的类型定义数组类型C语言中通过typedef为数组类型重命名 typedef type(name)[size];数组类型: typedef int(AINT5)[5]; typedef float(AFLOAT10)[10];数组定义:原创 2013-07-19 22:02:29 · 454 阅读 · 0 评论 -
C语言中的字符串
从概念上讲,C语言中没有字符串类型在C语言中使用字符数组来模拟字符串C语言中的字符串是以‘\0’结束的字符数组C语言中的字符串可以分配于栈空间,堆空间或者只读存储区char s1[] = {'H', 'e', 'l', 'l', 'o'}; //没有‘\0’,所以s1只不过是个单纯的字符数组char s2[] = {'H', 'e', 'l', 'l', 'o', '\0'}原创 2013-07-19 18:19:21 · 612 阅读 · 0 评论 -
数组与指针分析
指针就是指针,指针变量在32 位系统下,永远占4 个byte ,其值为某一个内存的地址。指针可以指向任何地方,但是不是任何地方你都能通过这个指针变量访问到。 数组就是数组,其大小与元素的类型和个数有关。定义数组时必须指定其元素的类型和个数。数组可以存任何类型的数据,但不能存函数。数组的本质:数组是一段连续的内存空间数组的空间大小为 sizeof(array_type)原创 2013-07-19 13:22:43 · 507 阅读 · 0 评论 -
编译过程简介
被隐藏的过程预编译:处理所有的注释,以空格代替将所有的#define删除删除 ,并且展开所有的宏定义处理条件编译指令#if, #ifdef, #elif, #else, #endif 处理#include ,展开被包含的文件保留编译器需要使用的#pragma指令指令预处理指令:编译:对预处理文件进行一系列词法分析 ,语原创 2013-07-17 00:11:02 · 403 阅读 · 0 评论 -
优先级和类型转换分析
易错的优先级typedef struct _demo{ int* pInt; float f;} Demo;int func(int v, int m){ return (v & m != 0); //优先级!=高于&,应改为return ((v & m) != 0); }int main(){原创 2013-07-16 22:58:23 · 561 阅读 · 0 评论 -
++、--操作使用分析
int i = 3;(++i) + (++i) + (++i)表达式的值为多少?15 吗?16 吗?18 吗?对于这种情况,C语言标准并没有作出规定。有点编译器计算出来为18,因为i 经过3 次自加后变为6,然后3 个6 相加得18; 而有的编译器计算出来为16(比如Visual C++6.0,gcc,g++ ),先计算前两个i 的和,这时候i自加两次,2 个i 的和为10,然后再加上原创 2013-07-16 21:34:33 · 574 阅读 · 0 评论 -
数组参数和指针参数的分析
为什么C语言中的数组参数会退化为指针?C语言中只会以值拷贝的方式传递参数,本质上还是传值,传地址也是传值,只不过传的是地址值当向函数传递参数时.将整个数组拷贝一份一份传入函数 错.将数组名看做常量指针传数组首元素地址 对C语言以高效为最初设计目标,在函数传递的时候,如果将拷贝整个数组执行效率将大大下降。 所以数组参数退化为指针原创 2013-07-20 00:39:04 · 566 阅读 · 0 评论 -
多维数组和多维指针
指向指针的指针指针变量在内存中会占用一定的空间可以定义指针来保存指针变量的地址int main(){ int a = 0; int* p = NULL; int** pp = NULL; pp = &p; //把指针变量p的地址赋给指针变量pp *pp = &a; //解引用pp可以把a的地址赋给p return 0;}int** pp本质上还是指针原创 2013-07-20 00:02:14 · 668 阅读 · 0 评论 -
指针基础
#include int main(){ int i = 5; int* p = &i; printf("%d, %08X\n", i, p); *p = 10; //等价于i = 10; printf("%d, %08X\n", i, p); return 0;}运行输出:原创 2013-07-18 18:00:22 · 487 阅读 · 0 评论 -
单引号和双引号
char* p1 = 1 ;char* p2 = '1'; ‘1’的ASCII码值为49char* p3 = "1“;0和49地址处为操作系统使用,故访问这些地址如printf("%s, %s, %s", p1, p2, p3)会产生段错误。printf('\n') \n的ASCII码值为10,同理,段错误。'a'表示字符常量,在内存中占1原创 2013-07-16 21:21:18 · 583 阅读 · 0 评论 -
基本数据类型分析
数据类型:数据类型可以理解为固定内存大小的别名数据类型是创建变量的模子数据类型的本质:内存大小的别名char代表1个字节,他就是1个字节的别名;short代表2个字节,他就是2个字节的别名;int代表4个字节,他就是4个字节的别名;......当需要1个字节时,把char这个模子拿到内存里一“咔”,1个字节内存就出来就可以使用了;当需要2个字节时,把sh原创 2013-07-17 10:40:26 · 540 阅读 · 0 评论 -
接续付和转义符
以反斜杠(\)表示断行。编译器会将反斜杠剔除掉,跟在反斜杠后面的字符自动接续到前一行。注意:反斜杠之后不能有空格,反斜杠的下一行之前也不能有空格。例://这是一条合法的\ 单行注释 -->//这是一条合法的单行注释/\ /这是一条合法的单行注释 -->//这是一条合法的单行注释#def\ ine MAC\ RO 这是一条原创 2013-07-16 21:22:43 · 581 阅读 · 0 评论 -
位运算符分析
注意按位运算符|和&与逻辑运算符||和&&完全是两码事,别混淆了。结合律:a&b&c (a&b)&c a&(B&c)交换律:a&b b&a 左移和右移左移运算符“高位丢弃,低位补0 。 右移运算符“>>”是双目运算符。其功能把“>> ”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。但注意:对于有符号数,当为正数时, 最高位补0 ;而原创 2013-07-16 21:33:14 · 759 阅读 · 0 评论 -
const和volatile分析
constconst 修饰的是只读变量,不是常量,会在内存中占用空间,本质上const只对编译器有用,在运行时无用const修饰的只读变量不能作为左值直接赋值,但可以通知指针修改其值const修饰的猪肚变量必须在定义的同时初始化case语句后面不可以跟const修饰的只读变量,case后面只能是整形或者字符型的常量或常量表达式const修饰的数组是只读的,const修饰的数组空原创 2013-07-16 21:27:33 · 534 阅读 · 0 评论 -
注释符号
1.int/*...*/i;正确,编译器会在编译过程删除注释,但不是简单的删除而是用空格代替2.char* s = "abcdefgh //hijklmn";正确,编译器认为双引号括起来的内容都是字符串,双斜杠也不例外3.//Is it a \ valid comment? 这是一条合法的注释,因为\是一个接续符4.in/*...*/t i; 错误,注释会被空格替换注原创 2013-07-16 21:24:32 · 791 阅读 · 0 评论 -
struct和union分析
struct空结构体大小,依据编译器的不同而不同,gcc中为0,且不同的结构体变量地址相同;而在g++中为1,不同的结构体变量地址也不同。没有谁对谁错,现代编译器中认为空结构体大小为1较为合理。柔性数组即数组大小待定的数组。规则:结构中最后一个元素允许是未知大小的数组; 结构中的柔性数组成员前面必须至少一个其他成员。typedef struct flex{原创 2013-07-16 21:25:51 · 516 阅读 · 0 评论 -
auto,register,static分析
C语言中的变量可以有自己的属性在定义变量的时候可以加上“属性”关键字“属性”关键字指明变量的特有意义auto即C语言中局部变量的默认属性,并且只能修饰局部变量;编译器默认所有的局部变量都是auto的;auto指明申明的变量在程序的栈上分配空间的static指明变量的“静态”属性;static同时具有“作用域限定符”的意义;static另一意义是文件作原创 2013-07-17 11:51:02 · 604 阅读 · 2 评论 -
#pragma预处理分析
#pragma是编译器指示字,用于指示编译器完成一些特定的动作#pragma所定义的很多指示字是编译器和操作系统特有的#pragma在不同的编译器间是不可移植的预处理器将忽略它不认识的#pragma指令,当预处理器看到#pragma后,就不会像处理#define,#include那样来进行进一步的处理,会把#pragma指令留给后续的编译模块,编译模块会根据他的参数执行一系列的动作,编原创 2013-07-18 12:18:41 · 663 阅读 · 0 评论 -
宏定义与使用分析
宏定义常量:#define宏定义常量可以出现在代码的任何地方#define从本行开始,之后的代码都可以使用这个宏常量以上宏定义都正确最后一个宏定义采用了接续符“\”,等同于#define PATH_3 D:\Delphi\CTopic3.ppt宏定义表达式#define表达式有函数调用的假象,却不是函数#define表达式可以比函数更强大#defi原创 2013-07-17 17:56:25 · 627 阅读 · 0 评论 -
goto,void,extern,sizeof分析
goto:禁用voidvoid:不允许定义void类型变量,但可以有void类型指针。void*:void* p指针可以接受任意类型指针,作为右值要赋值给左值类型指针必须强制类型转换,如 void* p1; int* p2; p1 = p2; //对, p2 = p1; //错,改为p2 = (int*)p1函数参数可以是任意类型指针,那么原创 2013-07-16 21:28:43 · 899 阅读 · 0 评论 -
#error、#warning和#line
#error的用法#error用于生成一个编译错误消息,并停止编译用法 #error message注:message不需要用双引号包围#error编译指示字用于自定义程序员特有的编译错误消息类似的,#warning用于生成编译警告,但不会停止编译例1:#include #define CONST_NAME1 "CONST_NAME1原创 2013-07-17 18:44:03 · 1776 阅读 · 0 评论 -
#和##运算符使用解析
#运算符用于在预编译期将宏参数转换为字符串例1:#include #define CONVERS(x) #xint main(){ printf("%s\n", CONVERS(Hello world!)); printf("%s\n", CONVERS(100)); printf("%s\n", CONVERS(while)); p原创 2013-07-18 16:10:30 · 411 阅读 · 0 评论 -
数组基础
编译器只给这20字节空间取了一个名字a,数组的每一个元素都没有名字。数组大小:数组在一片连续的内存空间中存储元素数组元素的个数可以显示或隐式指定int a[5] = {1,2}; //显示数组大小sizeof(a) = 20, 数组长度 sizeof(a)/sizeof(*a) = 5 ,指定数组长度,不管初始化列表有多少个元素,都会以指定的长度来作为唯一的指标分配原创 2013-07-18 23:05:00 · 462 阅读 · 0 评论 -
逻辑运算符&&、||、!使用分析
int i = 0;int j = 0; if( ++i > 0 || ++j > 0 ){ printf("%d\n", i); //输出1 printf("%d\n", j); //输出0}改为if( ++i > 0 && ++j > 0 ){ printf("%d\n", i); //输出1原创 2013-07-16 21:30:34 · 1412 阅读 · 0 评论