 |
i++,i--的前置,后置++i,--i的详细解释
|
|
| |
| 对i++,i--,++i,--i的易解,在此举一例子详解: main( ) { int x,y,z; x=y=2;z=3; y=x++-1;printf("%d\t%d\t",x,y); /*x=3,y=1,后置++,先把x赋值给y,再做运算,而x的值无论是前还是后置都加1*/ y=++x-1;printf("%d\t%d\t",x,y);/*x=4,y=3,前置++,先把x加1后赋值给y,然后做运算(此行x初值是上行的终值=3)*/ y=z--+1;printf("%d\t%d\t",z,y); /*z=2,y=4,同上理可知*/ y=--z+1;printf("%d\t%d\t",z,y); /*z=1,y=2,同理可证*/ getch(); } 希望能给初学者带来易处,你要多多发表和支持菜鸟的文章哟~~本文转载自IT网it求职笔试真题库网。
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1267次,回复0次 |
|
|
 |
C++和C的不同点
|
|
| |
| C++和C的不同点1.C++比C多了一种注释方式:双斜杠注释一次可注释一行. 例: int i; i=0; // 这一行是注释,下一行将i加一. i++;2.在C++中,变量可以随时处定义,而在C中必须在程序和函数的开始处定义. 例: /*这里是C的例子*/ int i; for(i=0;i<10;i++); //如果是C++可以将i在用时再定义. for(int i=0;i<10;i++);3.在C中声明一个struct结构,那么在用的时候要加上struct关键字,在C++中不需要.*同样的,enum结构和union结构中也是如此. 例: /*在C语言里*/ struct st {int x,y;}; /*用时:*/ struct st myst; //在C++中可以这样 struct st {int x,y;}; //用时: st myst;4.在C++中使用了新的IO库:iostream.h在C中只有stdio.h. 例: #include <i ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1432次,回复0次 |
|
|
 |
围绕p()与(*p)()的争论
|
|
| |
| 对于一个函数:void func(void);我们通常可以定义一个这样的函数指针指向它:void (*p)(void) = func;通过p调用func时,通常有两种写法:p();或者(*p)(); 围绕这两种写法,当初C89制定的时候曾经有过争论。(*p)();是一种旧式的规定,旧式规定圆括号左边必须具有“函数”类型,如果是指向函数的指针,那么必须加上*声明符。但C89不再把圆括号的左边限定为“函数”类型,而是一个后缀表达式。那么问题就来了,如果p的值是函数地址,那么*号就是声明符,但如果p指向的内容是函数地址,*号就得被看作运算符了。同一种形式会有两种解释,这是一个矛盾。不仅函数调用如此,指向数组的指针也存在这种矛盾。编译器为了处理这种情况得增加代码,效率自然就降低了。争论的最后结果是谁也不能把对方完全说服,于是就干脆两种都支持了。笔者认为应该抛弃旧式的规定,p();这种形式简洁明了,又符合函数的一般形式,何乐而不为? 第八章练习的答案,同时给出用typedef的分解方法:int (*(*func)[5][6])[7][8];func是一个指向数组的指针,这类数组的元素是一个具有5X6个int元素的二维数组,而这个二维数组的元素又是一个二维数组。typedef int (*PARA)[7][8];typedef PARA (*func)[5][6];int (*( ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1280次,回复0次 |
|
|
 |
指针与const
|
|
| |
| const一词是英文constant的缩写,设立这个关键字的本意,是希望让它所修饰的对象成为一个常量。记得在国家间的外交中,有一个经常用到的术语:“从事与身份不符的活动”,这个const恰恰也正从事着这样的活动,呵呵。C语言可以有三种方法定义一个常量:#define、const和枚举,但只有枚举才是真正的常量,什么是真正的常量?真正的常量是没有存储空间的,是一个右值,这意味着通过任何合法的手段也不会被修改,但被const修饰的对象依然是一个左值,尽管这个对象被const限定,笔者仍然至少可以找到三种合法的手段去修改它,而#define所做的只不过是编译期替换而已,只有枚举常量才能真正做到这一点。const实在不应该被命名为const,这会让人们产生误解,它应该命名为readonly或类似的字眼,意即不能通过被const修饰的对象修改它所指向的对象或者它所代表的对象。但在C的世界里把const称为常量早已是普遍的现象,那我们就只好随大流咯,也称之为常量吧,只要知道它实际上不是真正的常量就行了。 第七章曾经讨论过const int *p;与int * const p的区别,这两个声明的中文名称常常搞得混乱不堪。第一个声明的const是声明说明符,它修饰p所指向的对象,但p仍然是可变的,这意味着p是一个指向常量的指针,简称常量指针。第二个声明的const是声明符的一部分,它 ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1340次,回复0次 |
|
|
 |
右左法则----复杂指针解析
|
|
| |
| 上一章费那么多唇舌讨论C语言的声明,其实目的都是为了这一章,期望读者通过对C语言声明形式的详细了解,树立声明嵌套的观念,因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的:The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed. 这段英文的翻译如下:右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出 ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1266次,回复0次 |
|
|
 |
C语言声明详解
|
|
| |
| 人们常说,C语言的声明太复杂了,的确,这也是C语言饱受批评的地方之一。不过,笔者认为,真正要受到批评的不是语言本身,而是那些传播者。传播者们通常都有一个共识:讲述要由浅入深。作为原则,笔者并非要反对它,毕竟笔者对C语言的学习,也经历了相同的过程。但是,由浅入深并不意味着一切从简,以偏盖全。计算机语言不同于数学理论(虽然它的确根植于数学,与数学密不可分),数学理论是一种循序渐进的过程,后面的理论以前面的理论为基础。但C语言归根说底,就是一堆语言规则而已,应该让学习者一开始就全面且详细地了解它,而不是象现在某些教材所做的那样,只说一部分,不说另一部分,以为这就是由浅入深了,实际上这是以偏盖全。 语言如此,声明作为C语言的一部分更是如此。我们最常见到的对声明的描述是这样的:存储类别 类型限定词 类型 标识符这种说明会给人们一种暗示:C语言的声明是静止的、死板的,什么声明都能够以这个为基础,往上一套就OK了。事实真的如此吗?说句心里话,笔者也祈祷事实真的如此,这样世界就简单多了、清静多了。但别忘了,这个世界总是让人事与愿违的。实际上,C的声明的组织形式是以嵌套为基础的,是用嵌套声明组织起来的,并非象上面所述那么死板,存储类说明符一定得放在限定词前面吗?类型说明符一定要紧贴标识符吗?不!C标准从来没有这样说过!下面来看一看C89对声明的形式是如何规定的:声明:声明说明符 ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1277次,回复0次 |
|
|
 |
指向数组的指针
|
|
| |
| 讲到第五章了,数组两个字还离不开我们的左右,数组的内容也真多,另一方面也因为数组与指针的关系的确非常密切。 通常,对于int a[8][9]这个二维数组,我们可以这样定义一个指向它的指针:int (*p)[9];这个声明的形式跟人们所熟悉的int *p的形式大相庭径,初学者通常会感到迷惑,不理解的地方大致有四个:1。为什么会以这种形式声明?2。(*p)应该如何理解?3。为什么必须把第二维显式地声明?4。为什么忽略第一维?下面我们就一起逐个讨论这四个问题:1。这种形式是C标准的声明语法规定的,由于本章不是对标准的解释,只是对标准的应用,因此笔者尽量以简洁的方式解释这个声明,详细的讨论将在第七章进行。C标准的声明包含了两部分:声明:声明说明符 初始化声明符表opt (opt的意思是可选)在声明说明符里面有一项类型说明符,int就是这种类型说明符。而初始化声明符表里面的其中一种形式,就是:直接声明符 [常量表达式opt](*p)[9]就是这种直接声明符加[]的形式。2。p左边的*在这里不是取值运算符,而是一个声明符,它指出p是一个指针。而()括号是不能去掉的,如果去掉了,由于[]运算符优先级比*高,p就会先跟[]结合,这样p就变成了一个指针数组,而不是指向数组的指针。题外话:*p还有一种用法,就是当*是取值运算符的时候,*p是一个左值,表示一个变量,为什么* ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1344次,回复0次 |
|
|
 |
另类”数组
|
|
| |
| 动态数组与字符串常量可算是两种“另类”数组。 VLA可变长数组并不为C89所支持,C99才开始支持VLA。但如果想在只支持C89的编译环境中使用VLA的话,怎么办呢?我们可以用动态数组来“模拟”,动态数组在矩阵的运算中很常见,常用来向函数传递一个大小可变的矩阵。动态数组的原理,是利用一块或多块动态分配的内存存储各维的首地址,这样就可以p[j]的形式访问数组的数据了。但是,动态数组并非真正的数组,它只是对数组的一种模拟。由于具有数组类型的数组名是系统行为,在用户这一级没法做到,因此只能以指针的形式存放首地址,sizeof(p)和sizeof(p)结果都是4字节。虽然动态数组是依靠动态分配内存来建立的,但动态的意义并非来自这里,而是指大小可变。笔者觉得用“动态数组”这个名称来命名非常适合,既不失大小可变的特征,又可以跟VLA可变长数组区分开来。 下面是建立动态数组的示例:#include <stdio.h>#include <stdlib.h>void computedata(int *, int, int);int main(void){ int iData[100], x, y; do { printf("The product obtained by multiplying x a ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1227次,回复0次 |
|
|
 |
[ ]运算符的本质
|
|
| |
| 数组是存在于人们头脑中的一个逻辑概念,而编译器其实并不知道有数组这个东西,它所知道的,只是[]运算符,当遇到[]运算符的时候,编译器只是简单地把它转换为类似*(*(a+i)+j)这样的等价表达式,之所以是这种表达式,如前几章所述,是因为C语言的数组实现本质上是数组的嵌套。 由于这种等价关系的存在,会产生一些古零精怪的表达式,例如:10[a]这个表达式初看上去让人摸不着头脑,它是什么呢?如上所述,编译器会把它转换为*(10+a),把a和10调换一下,就是*(a+10)了,这个就是a[10]。[]运算符之前还可以是一个表达式,例如:(10+20)[a]。严格来讲,以上两个表达式是非法的,因为C89对于数组的引用(注意不是数组定义)规定:带下标的数组引用后缀表达式由一个后缀表达式后跟一个括在方括号中的表达式组成。方括号前的后缀表达式的类型必须为“指向T类型的指针”,其中T为某种类型;方括号中表达式的类型必须为整型。这个规定说明,进行数组引用的时候,[]运算符的左边并非必须为数组名,而可以是一个表达式,但这个表达式的类型必须为“指向某类型的指针”。显然10跟(10+20)连地址都不是,因此实际上他们是非法的,编译器在这里并没有严格遵守标准的规定。但如果是:int a[10], *p = a;(p+1)[2]这样就是合法的,因为p+1的结果仍然是一个指针。要注意的是,虽然后缀 ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1157次,回复0次 |
|
|
 |
char* a = "zhf"; 和 char a[] = "zhf"; 之间的区别
|
|
| |
| char* a = "zhf"; 定义一个 指针 a,指向一个 常量字符串 "zhf" 的首地址,由于 "zhf" 是一个常量字符串, 在常量区,无法修改,所以 a[1] = 'k' 出错,它意图修改常量;但是 a 这个指针本身是可以修改的。char a[] = "zhf"; 定义一个 char 数组,该数组的内容是 "zhf", 这里有一个赋值,"zhf" 被赋值给了这个数组, 数组中的值是可以修改的,也就是 a[1] = 'k' 是允许的;但是 数组名 是const 属性的, 不能修改。--------------------char *a[]="aaaaaaa";char *b="bbbbbbb"; aaaaaaaaaaa是在运行时刻赋值的; 而bbbbbbbbbbb是在编译时就确定的; 但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。 对应的汇编代码 10:a=c[1]; 004010678A4DF1movcl,byteptr[ebp-0Fh] 0040106A884DFCmovbyteptr[ebp-4],cl 11:a=p[1]; 0040106D8B55ECmovedx,dwordptr[ebp-14h] 004010708A4201moval,byteptr[edx+1] 004010738845FCmovbyteptr[ebp-4],al ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1164次,回复0次 |
|
|
 |
C++精华(STL)学习笔记之算法
|
|
| |
| <algorithm>是STL中最大得一个文件,它是由一大堆模版函数组成得。这些函数包括:max 检测两个元素得较大值min 检测两个元素得较小值swap 交换两个已储存得值iter_swap 交换两个由迭代器描述得值max_element 检测一个序列中较大得值min_element 检测一个序列中较小得值equal 比较两个序列是否相等lexicographical_compare 比较两个序列中一个序列是否排在另一个序列得前面mismatch 检测两个序列中第一个不相等得地方find 检测一个序列中第一个值等于给定值得位置 find_if 检测序列中第一个是pr(x)返回true得元素(pr是一个函数对象)adjacent_find 要检测第一对相等得相邻元素count 要计算一个序列中等于一个给定值得元素得个数count_if 计算一个序列中使ptr(x)返回true得个数得序列search 要在另外一个序列中检测一个序列第一次出现得地方search_n 要在一个序列中检测第一个连续出现n次指定值得地方find_end 要在另外一个序列中检测一个序列最后一次出现得地方find_first_of 要在一个序列中检测另一个序列中任意一个元素第一次出现得地方for_each 使用函数对象OP对序列中得每个元素都调用一次op(x)generate 要使用函数对象fun,将每个元素都 ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1471次,回复0次 |
|
|
 |
STL之vector容器
|
|
| |
| 标准模版类也定义了一个模版类basic_string,basic_string得一个模版参数是元素类型。他们之间得不同之处:basic_string得构造函数和析构函数只能在C程序中声明得类型,可以通过逐位复制得方式来位这样得对象赋值。vector则可以在其中包含任意类型。basic_string参数中需要一个traits类来为它得另一个模版参数,traits指定了如何移动或是比较序列中得元素,并且指定了如何读写由元素构成得文件。vector元素则不能使用这样得traits。basic_string对象可以移交以null结尾得序列,vector对象只理解我们存储在它里面的序列。basic_string对象可以使用写时复制,模版类vector则不行。basic_string对象还提供了一些与字符串处理相关得函数。标准C++库还定义了string是basic_string<char,char_traits<char>>得同义词。 vectro<bool> 模版类vector得特化版本,处理元素类型为bool得序列,可以更加经济得使用内存,将8个元素存储在一个相同得字节空间内,并定义了特殊得flip和swap处理函数; typedef vector<T,allocalor<T>> mycont; 通过使用默认得模版参数,可以省略第二个参数构造函数: vector() 声明一个空得ve ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1894次,回复0次 |
|
|
 |
把十进制数(long型)分别以二进制和十六进制形式输出
|
|
| |
| 编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列库函数char* test3(long num) {char* buffer = (char*)malloc(11);buffer[0] = '0';buffer[1] = 'x';buffer[10] = '\0';char* temp = buffer + 2;for (int i=0; i < 8; i++) {temp = (char)(num<<4*i>>28);temp = temp >= 0 ? temp : temp + 16;temp = temp < 10 ? temp + 48 : temp + 55;}return buffer;}本文转载自IT网it求职笔试真题库网。
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1448次,回复0次 |
|
|
 |
高质量C++/C编程指南
|
|
| |
| 比较经典的一本总结了c/c++最基本最重要,也是一些软件开发公司笔试的依据。本文转载自IT网it求职笔试真题库网。
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1284次,回复0次 |
|
|
 |
堆和栈的区别
|
|
| |
| 一、预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放5、程序代码区—存放函数体的二进制代码。二、例子程序 这是一个前辈写的,非常详细 //main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化区 main() { int b; 栈 char s[] = "abc"; 栈 char *p2; 栈 char *p3 = "123456"; 123456\0在常量区,p3在栈上。 static int c =0; 全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); 分配得来得10和20字节的区域就在堆区。 strcpy ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1269次,回复0次 |
|
|
 |
程序员陷阱题
|
|
| |
| 程序员陷阱题本文转载自IT网it求职笔试真题库网。
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1051次,回复0次 |
|
|
 |
linux中string库函数的实现,笔试时常考
|
|
| |
| /** linux/lib/string.c** Copyright (C) 1991, 1992 Linus Torvalds*//** stupid library routines.. The optimized versions should generally be found* as inline code in <asm-xx/string.h>** These are buggy as well..** * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>* - Added strsep() which will replace strtok() soon (because strsep() is* reentrant and should be faster). Use only strsep() in new code, please.** * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>,* Matthew Hawkins <matt@mh.dropbear.id.au>* - Kissed strtok() goodbye*/#include <linux/types.h>#inc ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1671次,回复0次 |
|
|
 |
基础理论的笔试真题,常考
|
|
| |
| 1. static有什么用途?(请至少说明两种)1.限制变量的作用域2.设置变量的存储域2. 引用与指针有什么区别?1) 引用必须被初始化,指针不必。2) 引用初始化以后不能被改变,指针可以改变所指的对象。2) 不存在指向空值的引用,但是存在指向空值的指针。3. 描述实时系统的基本特性在特定时间内完成特定的任务,实时性与可靠性4. 全局变量和局部变量在内存中是否有区别?如果有,是什么区别?全局变量储存在静态数据库,局部变量在堆栈5. 什么是平衡二叉树?左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于16. 堆栈溢出一般是由什么原因导致的?没有回收垃圾资源7. 什么函数不能声明为虚函数?constructor8. 冒泡排序算法的时间复杂度是什么?O(n^2)9. 写出float x 与“零值”比较的if语句。if(x>0.000001&&x<-0.000001)10. Internet采用哪种网络协议?该协议的主要层次结构?tcp/ip 应用层/传输层/网络层/数据链路层/物理层11. Internet物理地址和IP地址转换采用什么协议?ARP (Address Resolution Protocol)(地址解析?f?h)12.IP地址的编码分为哪俩部分?IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上 ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1197次,回复0次 |
|
|
 |
C/C++笔试小结
|
|
| |
| 1.void *p=malloc(100);sizeof(p)=4;---------------------指针的字节数,而不是指针指向的内容容量2. void Func(char str[100]){sizeof(str)=4;}--------------------数组作为函数的参数进行传递时,该数组自动退化为同类型的指针3.char str[100];sizeof(str)=100;--------------------不是函数的参数时4.char str[]="hello";char *p=str;int n=10;sizeof(str)=6;sizeof(p)=4;sizeof(n)=2;--------------------参考上面的5.#define A 3#define B 4#define C A+B#define s(x) x*xs(c)=A+B*A+B=3+4*3+4=19;-------------------宏展开只是简单的字符串替换6.一组碰到最多的题,至少4次笔试的题都有它,搞得我郁闷啊可参见林锐的《C/C++高质量编程》,很详细的解答了下面的题(1)void GetMemory(char *p, int num){ p = (char *)malloc(sizeof(char) * num);} void Test(void){ ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1402次,回复0次 |
|
|
 |
Linux守护进程的编程方法
|
|
| |
| 其实守护进程编程也没有什么难的,你只要掌握了一般的步骤就行了,而且 以后就可以将原来的那些程序块照搬过来。 下面是一篇文章,我想已经说得很清楚了,你自己好好看看吧。 ----守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且 周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进 程。Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd ,Web服务器httpd等。同时,守护进程完成许多系统任务。比如,作业规划进程 crond,打印进程lpd等。 ----守护进程的编程本身并不复杂,复杂的是各种版本的Unix的实现机制不尽相 同,造成不同Unix环境下守护进程的编程规则并不一致。这需要读者注意,照搬 某些书上的规则(特别是BSD4.3和低版本的SystemV)到Linux会出现错误的。下 面将全面介绍Linux下守护进程的编程要点并给出详细实例。 ----一.守护进程及其特性 ----守护进程最重要的特性是后台运行。在这一点上DOS下的常驻内存程序TSR与 之相似。其次,守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭 的文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩模等。这些 环境通常是守护进程从执行它的父进程(特别是shell)中继承下来的。最后,守 护进程的启动方式有其特殊之处。它可以 ...
|
|
| 作者:不祥 oases2008张贴于2005-01-01 00:00:00.0,共阅读1269次,回复0次 |
|
|