随笔分类 -  C/C++

摘要:浅析C/C++中的switch/case陷阱 先看下面一段代码: 文件main.cpp#includeusing namespace std;int main(int argc, char *argv[]){ int a =0; switch(a) { case ... 阅读全文
posted @ 2014-05-16 15:52 Matrix海子 阅读(59123) 评论(3) 推荐(3) 编辑
摘要:关于VC++6.0中getline函数的一个bug 最近在调试程序时,发现getline函数在VC++6.0和其他编译器上运行结果不一样,比如有如下这段程序:#include <iostream>#include <string>using namespace std;int main(void){ string str; getline(cin,str); cout<<str<<endl; return 0;} 在VC++6.0下运行时,比如说输入“123”,需要按两次回车键才会输出“123”。 而在C-Free和VS2010下运... 阅读全文
posted @ 2012-11-03 10:46 Matrix海子 阅读(3257) 评论(2) 推荐(1) 编辑
摘要:浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组的一些区别,然而在某些情况下,指针和数组是等同的,下面讨论一下什么时候指针和数组是相同的。C语言标准对此作了说明:规则1:表达式中的数组名被编译器当做一个指向该数组第一个元素的指针; 注:下面几种情况例外 1)数组名作为sizeof的操作数 2)使用&取数组的地址规则2:下标总是与指针的偏移量相同;规则3:在函数参数的声明中,数组名被编译器当做指向该数组第一个元素的指针。 规则1和规则2结合在一起理解,就是对数组下标的引用总是可以写成“一个指向数组的起始地址的指针加上偏移量”。如a[i]总是被编译器解析为*(a+i)的形式。规 阅读全文
posted @ 2011-11-09 15:23 Matrix海子 阅读(6468) 评论(20) 推荐(3) 编辑
摘要:浅谈C/C++中的指针和数组(一)指针是C/C++的精华,而指针和数组又是一对欢喜冤家,很多时候我们并不能很好的区分指针和数组,对于刚毕业的计算机系的本科生很少有人能够熟练掌握指针以及数组的用法和区别。造成这种原因可能跟现在大学教学以及现在市面上流行的很多C或者C++教程有关,这些教程虽然通俗易懂,但是在很多关键性的地方却避而不谈或者根本阐述不清楚,甚至很多时候阐述的是错误的观点。一般最初学习C/C++的时候接触到的都是这类教程,学习效果可想而知。对于初学者选择好的教程真的很关键,因为先入为主,一旦你接受了错误的观点或者思想即使后来知道了也一时很难纠正过来(我是深有体会),在此我推荐三本很适. 阅读全文
posted @ 2011-11-09 12:21 Matrix海子 阅读(18815) 评论(6) 推荐(1) 编辑
摘要:从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时,书中谈到C语言的声明问题,《C专家编程》这本书只有两百多页,却花了一章的内容去阐述这个问题,足以看出这个问题的重要性,要想透彻理解C语言的声明问题仅仅看书是远远不够的,需要平时多实践并大量阅读别人写的代码。下面借鉴《C专家编程》书中的两个例子来说说这个问题,以下很多内容是摘自《C专家编程》的第55页-79页。 在C语言中,声明的形式和使用的形式相似,这种用法可能是C语言的独创,K & R也承认"C语言声明的语法有时候会带来严重的问题"。C语言的声明存在的最大问题是你无法以一种人们所习惯的自然方式从左到右阅 阅读全文
posted @ 2011-11-04 16:17 Matrix海子 阅读(2002) 评论(1) 推荐(2) 编辑
摘要:浅谈C/C++中的typedef和#define 在C/C++中,我们平时写程序可能经常会用到typedef关键字和#define宏定义命令,在某些情况下使用它们会达到相同的效果,但是它们是有实质性的区别,一个是C/C++的关键字,一个是C/C++的宏定义命令,typedef用来为一个已有的数据类型起一个别名,而#define是用来定义一个宏定义常量。下面谈谈两者在实际使用中应当注意的地方。1.typedef关键字 typedef是用来声明类型别名的,在实际编写代码过程使用typedef往往是为了增加代码的可读性。它可以为一串很长的类型名起一个别名,那么使用这个别名可以达到与原类型名相同的效. 阅读全文
posted @ 2011-11-04 09:52 Matrix海子 阅读(6418) 评论(9) 推荐(3) 编辑
摘要:位运算和sizeof运算符 C语言中提供了一些运算符可以直接操作整数的位,称为位运算,因此位运算中的操作数都必须是整型的。位运算的效率是比较高的,而且位运算运用好的话会达到意想不到的效果。位运算主要有6种:与(&),或(|),取反(~),异或(^),左移(>)。1.位运算中的类型转换位运算都必须进... 阅读全文
posted @ 2011-11-02 21:32 Matrix海子 阅读(2531) 评论(2) 推荐(2) 编辑
摘要:从一个程序的Bug解析C语言的类型转换 先看下面一段程序,这段程序摘自《C 专家编程》:#include<stdio.h>int array[]={23,34,12,17,204,99,16};#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))int main(void){ int d=-1,x; /*........*/ if(d<=TOTALTOTAL_ELEMENTS-2) x=array[d+1]; /*........*/ return 0;} 如果是有这样一段程序的话,你永远无... 阅读全文
posted @ 2011-10-15 11:55 Matrix海子 阅读(2559) 评论(2) 推荐(4) 编辑
摘要:浅谈C语言中的位段 位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间。含有位段的结构体(联合体)称为位段结构。采用位段结构既能够节省空间,又方便于操作。 位段的定义格式为: type [var]:digits 其中type只能为int,unsigned int,signed int三种类型(int型能不能表示负数视编译器而定,比如VC中int就默认是signed int,能够表示负数)。位段名称var是可选参数,即可以省略。digits表示该位段所占的二进制位数。 那么定义一个位段结构可以像下面这段代码去定义:struct node{ unsigne... 阅读全文
posted @ 2011-10-14 21:15 Matrix海子 阅读(22940) 评论(5) 推荐(7) 编辑
摘要:C语言文件操作解析(五)之EOF解析 在C语言中,有个符号大家都应该很熟悉,那就是EOF(End of File),即文件结束符。但是很多时候对这个理解并不是很清楚,导致在写代码的时候经常出错,特别是在判断文件是否到达文件末尾时,常常出错。1.EOF是什么? 在VC中查看EOF的定义可知: #define EOF (-1) EOF只是代表一个整形常量-1。因此很多人认为在文件的末尾存在这个结束标志EOF,这种观点是错误的。事实上在文件的末尾是不存在这个标志的。那么有人会问那下面的程序如何解释? char ch; while((ch=fgetc(fp))!=EOF) { ... 阅读全文
posted @ 2011-10-13 16:39 Matrix海子 阅读(17427) 评论(1) 推荐(8) 编辑
摘要:C语言文件操作解析(四)在文件操作中除了打开操作以及读写操作,还有几种比较常见的操作。下面介绍一下这些操作中涉及到的函数。一.移动位置指针的函数 rewind函数和fseek函数,这两个函数的原型是:void rewind(FILE *fp); 将位置指针移动到文件首 int fseek(FILE *fp,long int offset,int origin); 将位置指针移动到距离origin的offset字节数的位置 其中对于fseek函数中的参数,origin为起始点,offset为距离origin的偏移字节数origin的值有三个:SEEK_SET(0)—>文件首,SEEK_CU 阅读全文
posted @ 2011-10-11 19:22 Matrix海子 阅读(1751) 评论(0) 推荐(0) 编辑
摘要:C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面说一下文件的读写操作。文件的读写操作主要有4种,字符读写、字符串读写、块读写以及格式化读写。一.字符读写 字符读写主要使用两个函数fputc和fgetc,两个函数的原型是: int fputc(int ch,FILE *fp);若写入成功则返回写入的字符,否则返回-1 int fgetc(FILE *fp); 若读取成功则返回读取的字符,否则返回-1注意:1)对于fputc函数和fgetc函数,每次操作,fputc只能写入1个字节的数据,无论参数ch多大,只将其低8位的数据写入到文件中;fgetc 每次只能返回一个字节的数据。2)对. 阅读全文
posted @ 2011-10-07 13:20 Matrix海子 阅读(5856) 评论(2) 推荐(3) 编辑
摘要:C语言文件操作解析(二)C语言中对文件进行操作必须首先打开文件,打开文件主要涉及到fopen函数。fopen函数的原型为 FILE* fopen(const char *path,const char *mode) 其中path为文件路径,mode为打开方式 1)对于文件路径,只需注意若未明确给出绝对路径,则默认该文件在工程的目录下。若需给出绝对路径,则注意转义字符'\',比如有文件test.txt存放在C盘根目录下,则文件路径参数值应为C:\\test.txt。 2)对于mode,主要由r,w,a,+,b,t六个字符组合而成。 r:只读方式,文件必须存在 w:只写方式,若文件 阅读全文
posted @ 2011-10-05 20:54 Matrix海子 阅读(31065) 评论(7) 推荐(1) 编辑
摘要:C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下与文件相关的东西。一.文本文件和二进制文件 文本文件的定义:由若干行字符构成的计算机文件,存在于计算机系统中。文本文件只能存储文件中的有效字符信息,不能存储图像、声音等信息。狭义上的二进制文件则指除开文本文件之外的文件,如图片、DOC文档。 事实上,无论是上面所定义的文本文件还是二进制文件,在计算机中存储都是以二进制的形式存储的,因此其本质并没有区别。所以广义上的二进制文件便指所有的文件。 通常意义下,我们所说的文本文件指只包含了纯文本信息的文件(通过手动编辑完成,包含的都是可显字符),二进制文件特指文件里面存储的是二进制代码的文件. 阅读全文
posted @ 2011-10-05 15:17 Matrix海子 阅读(6361) 评论(1) 推荐(3) 编辑
摘要:联合体union 当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。在C Programming Language 一书中对于联合体是这么描述的: 1)联合体是一个结构; 2)它的所有成员相对于基地址的偏移量都为0; 3)此结构空间要大到足够容纳最"宽"的成员;4)其对齐方式要适合其中所有的成员;下面解释这四条描述: 由于联合体中的所有成员是共享一段内存的,因此每个成员的存放首地址相对于于联合体变量的基地址的偏移量为0,即所有成员的首地址都是一样的。为了使得所有成员能够共享一段内存,因此该空间必须足够容纳这些成员中最宽的成员。对于这句“对齐方式 阅读全文
posted @ 2011-10-03 13:13 Matrix海子 阅读(55478) 评论(11) 推荐(15) 编辑
摘要:C/C++浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100。则在Intel CPU架构的系统中,存放方式为 10000100(低地址单元) 00000100(高地址单元),因为Intel CPU的架构是小端模式。但是对于浮点数在内存是如何存储的?目前所有的C/C++编译器都是采用IEEE所制定的标准浮点格式,即二进制科学表示法。 在二进制科学表示法中,S=M*2^N 主要由三部分构成:符号位+阶码(N)+尾数(M)。对于float型数据,其二进制有32位,其中符号位1位,阶码8位,尾数2. 阅读全文
posted @ 2011-10-02 22:01 Matrix海子 阅读(50403) 评论(12) 推荐(10) 编辑
摘要:大端和小端 嵌入式开发者应该对大端和小端很熟悉。在内存单元中数据是以字节为存储单位的,对于多字节数据,在小端模式中,低字节数据存放在低地址单元,而在大端模式中,低字节数据存放在高地址单元。比如一个定义一个short型的变量a,赋值为1,由于short型数据占2字节。在小端模式中,其存放方式为0X4000 000000010X4001 00000000而在大端模式中,其存放方式为0X4000 000000000X4001 00000001若需用程序验证系统是大端模式还是小端模式(一般我们用的x86结构的都是小端模式),有两种方法1.利用联合体的性质 因为联合体中的成员是共享内存的,并且数据是从. 阅读全文
posted @ 2011-10-01 23:29 Matrix海子 阅读(1682) 评论(0) 推荐(2) 编辑
摘要:看下面一道面试题:#include<stdio.h>#include<stdlib.h>int main(void) { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); printf("%d,%d",*(a+1),*(ptr-1)); return 0;} 输出结果为:2,5在这里主要是考察*(a+1)和&a+1的区别了。很显然*(a+1)取的是a[1],然而&a+1取的是什么呢?&a不是首地址加1,而是加上1个a数组大小的偏移。因此ptr实际上等于a+5,所以*(ptr-1 阅读全文
posted @ 2011-09-26 17:07 Matrix海子 阅读(2103) 评论(0) 推荐(1) 编辑
摘要:结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排列,而不是简单地顺序排列,这就是内存对齐。 内存对齐的原因: 1)某些平台只能在特定的地址处访问特定类型的数据; 2)提高存取数据的速度。比如有的平台每次都是从偶地址处读取数据,对于一个int型的变量,若从偶地址单元处存放,则只需一个读取周期即可读取该变量;但是若从奇地址单元处存放,则需要2个读取. 阅读全文
posted @ 2011-09-17 10:48 Matrix海子 阅读(19128) 评论(22) 推荐(12) 编辑
摘要:一.C语言中的static关键字 在C语言中,static可以用来修饰局部变量,全局变量以及函数。在不同的情况下static的作用不尽相同。 (1)修饰局部变量 一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存放在静态数据区,其生命周期一直持续到整个程序执行结束。但是在这里要注意的是,虽然用static对局部变量进行修饰过后,其生命周期以及存储空间发生了变化,但是其作用域并没有改变,其仍然是一个局部变量,作用域仅限于该语句块。 在用static修饰局部变量后,该变量只在初次运行时进行初始化工作,且只进行一 阅读全文
posted @ 2011-04-20 20:06 Matrix海子 阅读(18822) 评论(0) 推荐(2) 编辑