C语言C++程序员编程必备

2024-07-02

C语言C++程序员编程必备(精选7篇)

篇1:C语言C++程序员编程必备

Java,NET,PHP,Ruby,Perl 和 Python 等,但今天我们要讨论的是两个最古老和流行的语言的C和C++。它们都有其特殊的地方,更有效的功能和支持的工具,这两种语言仍然很活跃。

今天我们整理了一些令人印象深刻的IDE(集成开发环境)和编译器推荐给 C 和 C++ 程序员。集成开发环境,主要用于提供软件应用的各种组件而开发的,其中最流行的功能是它们都有吸引力的用户界面。1)Best IDE for C/C++ – kDevelop KDevelop 是基于 KDevPlatform 的可使用开源插件扩展的 IDE。KDevPlatform 是一种可以用来作为 IDE 的基础库的开源集。

2)Best IDE for C/C++-Anjuta Anjuta Devstudio 具有先进的编程工具,包括项目管理,应用程序向导,交互式调试器,源代码编辑器,版本控制,GUI设计器,分析器和许多工具,另一个伟大的开发工作室。此工具提供的 C/C++ 程序员有很大强大的用户界面开发接口。

3)Best IDE for C/C++Eclipse CDT Eclipse CD 是最强大和最流行的IDE之一,提供了更高效的功能,如:项目的创建和管理,构建支持不同的工具链,标准make编译,源代码导航,各种来源的知识工具,代码编辑器,语法高亮,折叠和超链接导航,源代码重构和代码生成,可视化调试工具,包括内存,寄存器等等。

7)Best IDE for C/C++ – Compilr Compilr 是在线集成开发工具,让您与令人印象深刻的功能和简单的用户界面编写代码。该工具支持的编程语言中广泛的C,C + + JAVA,HTML等等。

8)Best IDE for C/C++Netbeans C++ Netbeans 的工具包括许多适合 C 和 C++ 项目类型模板,可以 使用动态库和静态创建 C/C++ 应用程序库。它拥有迷人的功能:代码协助,编译器配置,单元测试,源检查,远程开发和文件导航等等。

10)Best IDE/Compiler for C/C++Ultimate++ Ultimate++是对于 C++ 程序员来说是很好框架。这个 IDE 引入了模块化概念,可以结合 GCC,MinGW 和 Visual C++。

12)Best Compiler for C/C++-Digital Mars DigitalMars 是一款高性能的 C/C++ 编译器。包括的功能,如速度最快的编译/链接时,强

HTML文档,反汇编,图书管理员,资源编译器,make等,命令行和GUI版本,教程,代码示例,在线更新,标准模板库等等。

13)Best IDE for C-C-Free

14)Best Compiler for C/C++ – MinGW MinGW 编译器提供访问微软的C运行库和一些特定语言运行库的功能。

15)Best Compiler for C – Tiny C Compiler iny C Compiler 是最好的编译器之一,让开发人员可以在任何地方编译代码,可以使用任何 C 动态库,编译并直接执行C++源程序,也包含完整的 C 预处理器和 GNU 汇编器。

@扣丁学堂 智悦分享

篇2:C语言C++程序员编程必备

1、赋值构成一个表达式,具有值,其值为赋值符左边表达式的值。表达式和语句的一个重要区别是,表达式有值,而语句没有值。

2、隐式类型转换总是朝着表达数据能力更强的方向,并且转换总是逐个运算符进行的。如 float f=3.5;int n=6;long k=21;double ss=f*n+k/2;//在计算ss时,首先将f和n转换成double,算得21,然后计算k/2得10,再将10(long int)转换成double,最后得31。

27、C++基础笔记(一)墨涵天地 有符号数向无符号数转换。

3、当又有声明又有定义时,定义中不允许出现默认参数,如果函数只有定义,才允许默认参数出现在定义中。默认值可以是一个全局变量,全局常量,或是一个函数,但是不能是局部变量,因为默认参数的函数调用是在编译时确定的,而局部变量的位置和值在编译时是无法确定的。如 int a=1;void fun(){ int i;void g(int x=i);//not right int g(int x=a);//right

}

4、define宏定义指令

1)使用其定义常量已被C++中的const定义语句所代替。2)用来定义带参数的宏,已被C++的内联函数所代替。3)其一个有效的使用是在条件编译中。

5、编译时必须知道数组的大小。如

int a[]={1,2,3,4,5};//编译器会自动去数 for(int i=0;i

7、Free和malloc int* a;a=(int*)malloc(sizeof(int));cout<

8、指向常量的指针,指针常量,指向常量的指针常量

指向常量的指针:通过指针不能改变所指向的变量的值,但是指针的值可以变化(即指针可

以指向其它变量的地址)。形式如const int* pi=&a;原来的变量的访问属性也不会发生改变,如原来是普通变量,则其值可以变化,原来是常变量,则其值不能变化。

指针常量:在定义时必须初始化,且一旦赋值,则以后该指针的值将不会再发生变化(即不能再指向其它地址)。形如char* const pc=“abcd”;注意,pc的值是不能再改变了,但是*pc的值可以变化,如*pc=b;指向常量的指针常量:具有上述两具指针的特点,须在定义时初始化,且一旦赋值,则以后该指针的值将不会再发生变化,且通过指针不能改变所指向的变量的值,形如const int* const cpc=“perfect”;注意,这种情况下,*cpc的值也是不能改变的,如*cpc=n是不对的。int main(){ char* const pc=“abcd”;cout<

}

9、sum(int array[],int n)与sum(int* array,int n)是等价的。

10、函数返回值,可以返回堆地址,也可以返回全局或静态变量的地址,但是不能返回局部变量的地址。

11、void指针是空类型指针,它不指任何类型,它仅仅是一个地址,不能进行指针运算,也不能进行间接引用。

NULL与void* 是不同的概念,NULL是一个指针值,任何类型的指针都可赋予该值。而void* 是一种类型(语法上是一个类型,本质上不是,没有任何一个变量或对象,其类型为void),是一种无任何类型的指针。不允许对void进行引用。

12、由引号(“ ”)标识,但不是用来初始化数组的字符串,是字符串常量,如cout<<“hello”<

由于字符串常量的地址属性,两个同样字符组成的字符串常量是不相等的,字符串常量的比较是地址的比较。

字符串常量,字符数组名(常量指针),字符指针均属于同一种数据类型。

13、不能建立引用的数组,因为数组是某个数据类型的集合,数组名表示起始地址,它不是数据类型。如 int a[10];int& a1[10]=a;//not right 引用本身不是一种数据类型(int&不是类型,定义时也不产生内存空间),所以没有引用的引用。也没有引用的指针。引用是变量或对象的引用,而不是类型的引用,所以有空指针,但是没有空引用。Int& ri=NULL //没有意义

可以用引用返回值。在通常情况下,C++会建立一个临时变量以将函数返回值带回。但是如果用引用,则不用建立临时变量。

C++规定,临时变量或对象的生命周期在一个完整的语句表达式结束后便宣告结束。所以如果以返回值初始化一个引用,应当先建立一个变量,将函数返回值赋于这个变量,作如下处理:

int x=fn1(5.0);//在这一句后临时变量生命周期将结束 int& b=x;************************* float temp;

float& fn2(float r){ temp=10*r;return temp;} 用如上的方法,则函数返回值将不再创建临时变量,而直接与全局变量temp共享内存单元 ******************************* 以引用的初始化,可以是变量,也以是常量,也可以是一定类型的堆空间变量,但是引用不是指针,如下表达是不对的: int& a=new int(2);

//not right

下面是用堆空间变量初始化引用的一个例子: #include #include using namespace std;int main(){ double* pd=new double;if(pd==NULL){printf(“failed”);exit(1);} cout<

//...{

cin>>rd;

cout<

cout<<&rd;

} delete& rd;//或delete pd return 1;}

注意:用double& rd来定义引用,而&rd则是取引用所指向的空间的地址。

14、声明一个结构并不分配内存,内存分配发生在定义这个新数据类型的变量中。结构不像数组,结构变量不是指针,&结构变量 取到的是结构中第一个成员变量的地址。结构变量可以相互赋值。结构成员不能作自身的结构变量,但是可以用结构指针作为成员。

15、将类定义和其它成员函数定义分开,是目前开发程序的通常做法。我们把类定义(头文件)看成是类的外部接口,类的成员函数定义看成是类的内部实现。

篇3:C语言C++程序员编程必备

关键词:C++程序,C程序,转换探讨

一、C++与C程序概述

C++是在C的基础上演变而来的, C++与C区别最大的就是C++中的类的概念和特性, 将C++改为C的问题, 就转换成如何将类化去的问题。方法有两种:第一种是将C++中的面向对象特征去掉, 先全部理解源代码的逻辑, 然后改写;第二种是在C中保留面向对象的部分特征, 用结构体实现类的功能。第一种方法, 对于类的数目很少的情况还可以, 如果类的数目比较多, 全部理解源代码, 然后重写就很耗时间, 而且很容易出错, 更甚者, 如果遇到大的项目想全部理解源代码几乎是不可能的。这个时候就需要采用第二种方法了, 你可以一个类一个类的改没有什么太高的难度, 如果没有笔误的话, 几乎不会出错, 而且根本不需要理解程序逻辑, 也许改完后你对程序所要实现的功能还一无所知。这倒不是说一无所知对大家有好处, 只是说这种方法的与程序逻辑本身的无关性。所以, 在此用第二种方法对C++的一些特性, 以及如何在C里实现或者替代, 作一些初步的探讨。

二、C++程序到C程序的转换

为了便于下面的讨论先做几点说明:

1. 函数Ixx为类xx的构造函数的实现。

2. 原类的成员函数改为前缀为 结构体名+‘_’的函数。

3. 函数指针U为原类的析构函数的声明;

4. U+结构体名称 为原类的析构函数的实现;

5. Fun_+结构体名 为对该结构体成员函数指针进行指向。

以后遇到上述情况将不再说明。

(一) 类的成员函数和数据成员

由于struct没有对成员的访问权限进行控制, 必须加入额外的机制进行访问控制, 这样一来就使得程序复杂化了, 所以只能放弃访问权限的控制。

1.对于类的数据成员可以直接转为C中结构体的数据成员。

2.函数则需转化为对应的函数指针, 因为struct里不允许出现函数的声明和定义。而函数前如果有virture, inline等修饰符也要去掉, 如函数void funca (int a) ;改为void (*funca) (struct B *p, int a) ;大家可以看到函数指针的原型里加了一个指针struct B的指针, 这是因为要在函数内部对类的成员进行操作, 要靠该指针指定结构体的成员。在类的成员函数里, 实际上在参数列里也隐含有一个指向自身的this指针。

3.对于静态成员则要定义成全局变量或全局函数, 因为结构体中不能有静态成员。

(二) 类的构造函数

类在实例化的时候会调用类的缺省构造函数, 在struct里, 要定义一个同名函数指针指向一个具有构造函数功能的初始化函数, 与构造函数不同的是, 要在初始化函数里加入进行函数指针初始化的语句。使用的时候在创建结构体变量的时候要用malloc而不是new, 并且这个时候要手工调用初始化函数。

(三) 类的析构函数

类的析构函数所作的工作是释放所占的资源。

在C中, 无论是哪个struct都用函数指针U替代析构函数。之所以所有的struct都用指针U是基于如下情况:

如果将子类指针赋给基类指针, 基类指针在释放的时候不必考虑调用哪个函数名的析构函数, 只需调用成员函数U即可。成员函数U需要像一般成员函数一样在fun_类名 () 函数中指定。

类的析构函数是由系统调用的, 在C中则要显式调用。至于何时调用, 要准确判断。

(四) 类的拷贝构造函数

类的拷贝构造函数主要用途是加快以下情况下类的构建速度:

1.作为参数传给函数。 (additem (Itema) )

2.作为函数返回值。

3.实例化类时作参数。

这三种情况下都是由系统直接调用类的拷贝构造函数而不是构造函数。

注意:C=D;不会调用拷贝构造函数, 这种情况下使用的是重载‘=’运算符的方法。 (详见运算符重载) ;

由于C中定义struct变量的时候, 使用的全部是指针, 不会用到拷贝构造函数, 所以暂不考虑。对于原来函数参数或者返回值需要类变量的, 要全部转化为类指针的方式。实例化类时作参数的情况, 可以通过另外定义一个带参数的构造函数来解决。

(五) 类的内联函数和虚函数

内联函数和虚函数的修饰符inline 、virture 要全部去掉。内联函数体则要去掉, 将内联函数在外面定义成一个函数。如:

(六) 重载

类中重载有函数重载和运算符重载两种:

1.函数的重载

函数重载满足的条件是:函数名相同, 参数个数或者参数类型不同。这样在调用的时候, 会根据你输入的参数不同, 调用不同的函数。在C中只好分别起不同的名字, 没有别的解决办法。

2.运算符重载

运算符重载只是为了满足一般的运算符使用的习惯而又不会出现错误。C中不支持运算符重载, 可以定义一个函数实现该功能。这是一般类的修改。

(七) 类的继承

1.单继承

如果类之间有继承关系, 先将基类按照一般类的改法, 修改好。然后将基类的定义部分全部拷到子类的前头。除了将基类的构造函数名改为子类构造函数名外, 不可以将基类定义的部分作其他改动。并在构造函数里调用基类的构造函数, 然后如果子类覆盖了基类的函数, 则要把该函数指针重定向到子类函数。这是为了保持类的继承带来的动态联编的特性。

类之间的继承关系是复杂且多变的, 为了保证基类在所有子类中的唯一而且方便修改, 最好的方法就是把基类的结构体部分做成宏, 在子类中直接使用即可。

2.多继承

我个人认为多继承是最好不要用, 他会带来一些问题, 会出现多个继承路径的问题。除非是为了方便编程而使用的, 如继承接口等等。

多继承也是可以改的, 将多个基类的成员全部拷到子类里, 遇到重复的成员名, 则在前面加上前缀来区别, 当然这个指的是基类之间有相同的, 如果是派生类和基类之间有重名的, 则会覆盖基类。

三、结束语

以上就是C++中主要的与C区别最大而且最常用的特性及修改方法。其他的还有一些比如模板的使用等等, 这些都是为了方便编程, 复用代码。C中没有, 只好自己写多个函数来分别实现。另外还有参数列表里的&符号要用指针替代, 缺省值也要去掉, 而在调用的时候要注意将缺省值写上。

参考文献

[1]蔡立军, 杜四春, 银红霞.C++程序设计[M].北京:清华大学出版社, 2004.

[2]丁芝芳, 刘杰.数据结构:C++语言描述[M].北京:清华大学出版社, 2004.

[3]波尔 (美) .C++面向对象编程[M].北京:电子工业出版社, 2004.

[4]谭浩强.C语言程序设计[M].北京:清华大学出版社, 2000.

篇4:C语言C++程序员编程必备

关键词:教学改革C++程序设计语言课程实践

1.学习C ++语言的重要性

C ++语言是最有活力和应用最广的程序设计语言之一,是从事计算机软件开发和应用人员必备的专业基础,是以后学习“数据结构”课程的先修课程。C 语言具有功能强大、效率高、简洁灵活和可移植性强的特点,而C ++语言不仅继承了C 语言的所有优点,而且支持面向对象的程序设计,因而在软件开发领域深受编程人员的喜爱。在高校C ++程序设计语言大多数作为计算机专业学生的入门课程,通过对该课程学习,学生掌握了基本的编程思想,为以后学习其他编程语言打下坚实的基础。但從目前的教学和课程实践情况来看,学生在学习C ++程序设计语言时往往存在着一定的问题,实践能力和实际掌握的情况并不太理想。

2.目前C ++语言教学中存在的问题

2.1 采用多媒体的讲授方式,教学效果差

目前大多数高校都以多媒体教学为主,此种教学方式比传统的黑板板书讲授有了很大的进步,但仍存在着不少问题。首先,这种教学与传统的教学方法相比并没有发生质的变化,在整个授课过程中,教师仍起着主导作用,很难激发学生学习的热情,容易导致学生注意力不集中,影响教学效果。其次,目前很多教师忙于自己的科研,很少有时间去研究修改课件,导致课件单调乏味,无法吸引学生的注意力,学生学习的热情也会随之消失得无影无踪。

2.2 C ++语言本身的特点给学生学习带来难度

C++并非是纯面向对象的语言,兼具面向过程和面向对象的特点,继承了C的所有优点,具有强大的编程功能和自由灵活的编程风格,得到了编程人员的广泛青睐,但是这些优点却增加了初学者的学习难度。再加上该课程往往在大一开设,此时学生刚经过高考的压力,想着要好好放松一把,而且他们缺乏对计算机结构的全面了解,因此学生很难理解和掌握该语言和计算机硬件尤其是和内存结合很紧密的一些概念。此外,在部分高校中,只开设C ++程序设计语言课程,而不开设C 语言课程,那么就等同于学生得在一个学期内学两门语言,而时间并无增加,这样一来学生掌握起来更为困难。

2.3 未能使用主流的开发工具平台,开发工具陈旧。

部分高校仍采用 VC6.0 作为开发工具,而VC6.0 产生于十多年前,对标准 C++的支持力度不够。 而目前主流的 C++开发工具 Visual Studio 2005.Net 是微软于2006 年新推出的开发平台,功能强大,已成为许多软件公司的首选开发工具。 若能采用 Visual Studio 2005.Net 作为 C ++程序设计语言课程中的开发平台,则能给学生今后就业打下坚实的基础。

2.4 当前考试形式注重应试忽视实践导致学生实践能力差

从目前情况来看,大多数的有关C ++语言的考试还处在原来的应试教育阶段。作为一门实用编程语言,考试时理论知识考得多,动手能力考的少,而学生学习一般都为了应付考试,这就使得大多数学生不注重动手实践能力的培养,而仅仅是靠做题和背题来通过考试,殊不知动手能力才是第一位的,也是以后就业的保障,只有在实际的编程锻炼中,才能更好地掌握C ++语言。虽说大多数高校都开设有C ++程序设计语言相关上机实践课,但是实践课的人数一般都过多,而老师只有一个,很难掌控所有的学生。

3.C ++语言教学改革与实践的几点建议

3.1 教学方式和教学方法的改革

(1)改进教学方式

改变传统的纯多媒体的讲授方式,将多媒体授课转换到机房授课,这样一来,教师讲完理论知识后,举一个实际例子加以阐述,然后马上由学生上机实践,使得学生能及时上机验证,加深对本节所学的基本理论和基本方法的理解,并加以应用。

(2)改革教学方法

改变当前的教学方法。在目前的教学模式中,一般教师都处于主导地位,是整个教学活动的中心,而学生始终处于被动地位,这就削弱了学生的积极性,影响了其主动性的发挥。建议采取提问和讨论的教学模式,弱化教师的主体地位,强化学生的主体地位。每节课都应有和理论相关的实践例子,让学生进行讨论学习,并对于相关例子找出新的解决方法,开拓学生的思维,以编程实践的方式让他们验证、理解和掌握所学理论知识,完成本节教学任务。

(3)加强课件建设

教师应多花时间研究出能吸引学生的优秀课件。可通过每隔一段时间就在一个群体单位中举行课件大赛,然后从交互性、趣味性、动态性、内容的充实性等方面挑选出优秀的课件供本单位的教师所用,使好的资源得到充分共享,从而充分激发学生学习的兴趣,加深他们对所学内容的理解,调动学生学习的自觉性和主动性。

3.2 明确学习目标,提高动手能力

C++语言同时具有面向过程和面向对象的特点,学习这门课程是有难度的,教师应在第一节课告知学生,并明确学习该课程的目标并不是只有了应付考试,而是要掌握基本的编程能力和学习编程语言的方法,为今后学习相关专业课程和就业打下坚实的基础。此外,要提高学生的动手能力。上机实践课时,教师很难掌控所有的学生,那么可以采用布置任务和奖励的方式加以控制。课程考试成绩一般都有期末成绩和平时成绩两部分组成,而平时成绩一般都是由教师决定的,那么教师可以充分利用平时成绩的灵活性来提高学生学习的主动性。实践课时,教师根据所学知识布置实践的内容,然后让学生自主完成,最后根据完成的程度给学生平时成绩加上相应的分数。这样一来,部分学生为了取得更高的分数,就是减少玩的时间,增加学习的时间,进而在一定程度上提高学生的动手能力。

3.3 采用最新的教学材料

计算机的相关知识更新速度快,有的教师为了省事一直采用老教材,这样就会影响学生对最新知识的学习。比如老教材介绍C++语言时使用VC6.0 作为开发环境,而目前主流的使用Visual Studio 2005.Net作为开发环境,还使用老教材的话,就会影响学生对Visual Studio 2005.Net环境的学习,而大多数公司都是采用Visual Studio 2005.Net作为开发环境的,这样一来就给学生今后的就业带来不利影响。 由此看来,教师不应与新知识脱节,应不断的了解相关课程的最新发展,及时更新教学材料,跟上学科前进的脚步。

3.4 改变考试方式

目前而言,高校对C ++语言课程考试方式大多数以理论知识为主,并不注重动手能力考核,这往往会导致学生学习没有动力,满足于考试及格顺利拿到学分毕业就行,从而失去了学习C ++语言的本意。 建议改革现有考试方式,采取了“理论考试+上机实践+平时成绩”相结合的考试模式,少考或不考理论知识和语法,加强能力的考核,增加上机实践考试引导学生对实际编程能力的重视,培养学生实际编程能力。

4.小结

经过对C ++语言教学现存在问题的分析,从教学方式和方法、教学材料和考试方式等多方面入手,根据本人在从事C++语言教学过程中的几点体会,总结出来几点建议,仅供各位同行参考。

参考文献:

[1]吴乃陵,况迎辉.C++程序设计(第2版)[M].北京:高等教育出版社,2006.

篇5:C语言C++程序员编程必备

分类: C语言学习心得体会 2010-08-08 19:33 63人阅读 评论(1)收藏 举报

转载请注明出处:http://blog.csdn.net/ecorefeng

在编程过程中会遇到各种各样的错误与警告,这里我对编程过程中经常遇到的细节或者说常出错的地方进行了简单的总结,希望对正在编程的“童鞋”有所帮助:

C语言编程提示的总结:

1:使用 #include 指令避免重复声明

2:使用 #define 指令给常量值取名

3:在 #include 文件中放置函数原型

4:在使用下标前先检查它们的值

5:在 while 或 if 表达式中蕴含赋值操作

6:如何编写一个空循环体

7:始终要进行检查,确保数组不越界

8:良好的程序风格和文档将使程序容易阅读和维护

9:为了保持最佳的可移植性,把字符的值限制在有符号和无符号字符范围的交集之内,或者不要在字符上执行算术运算

10:用它们在使用时最自然的形式来表示字面值

11:不要把整型值和枚举值混在一起使用

12:不要依赖隐式声明

13:在定义类型的新名字时,使用 typedef 而不是 #define

14:用 const 声明其值不会修改的变量

15:使用名字常量而不是字面值常量

16:不要在嵌套的代码块之间使用相同的变量名

17:在一个没有循环体的循环中,用一个分号表示空语句,并让它独占一行

18: for 循环的可读行比 while 循环强,因为它把用于控制循环的表达式收集起来放在一个地方

19:在每个 switch 语句中都使用 default 子句

20:使用符号赋值符可以使用程序更容易维护

21:使用条件操作符代替 if 语句以简化表达式

22:使用逗号操作符来消除多余的代码

23:不要混用整型和布尔型值

24:一个值应该只具一种意思

25:如果指针并不指向任何有意义的东西,使它非法地指向了数组第 1 个元素的前面的内存位置

26:在函数原型中使用参数名,可以给使用该函数的用户提供更多的信息

27:抽象数据类型可以减少程序对模块实现细节的依赖,从而提高程序的可靠性

28:当递归定义清晰地优点可以补偿它的效率开销时,就可以使用这个工具

29:一开始就编写良好的代码显然比依赖编译器来修正劣质代码更好

30:源代码的可读性机会总是比程序的运行时效率更为重要

31:只要有可能,函数的指针参都应该声明为 const

32:在有些环境中,使用 register 关键字提高程序的运行时效率

33:在多维数组的初始值列表中使用完整的多层花括号能提高可读性

34:不要试图自己编写功能相同的函数来取代库函数

35:使用字符分类和转换函数可以提高函数的移植性

36:把结构标签声明和结构的 typedef 声明放在头文件中,当源文件需要这些声明时可以通过 #include 指令把它们包含进来

37::结构成员的最佳排列形式并不一定就是考虑边界对齐而浪费空间最少的那种排列形式

38:把位段成员显示地声明为 signed in 或 unsigned 类型

39:位段是不可移植的40:位段时源代码中位的操作表达得更为清楚

41:动态内存分配有助于消除程序内部存在的限制

42:使用 sizeof 计算数据类型的长度,提高程序的可移植性

43:消除特殊情况使代码更容易维护

44:通过锻炼语句消除 if 语句中的重复语句

45:不要仅仅根据代码的大小评估它的质量

46:如果并非必要,避免使用多层间接访问

47: cdecl 程序可以帮助你分析复杂的声明

48:把 void* 强制转换为其他类型的指针时必须小心

49:使用转移表时,应始终验证下标的有效性

50:破坏性的命令行参数处理方式使你以后无法再进行处理

51:不寻常的代码始终应该加上一条注释,描述它的目的和原理

52:避免用 #define 指令定义可以用函数实现的很长序列的代码

53:在那些对表达式求值的宏中,每个宏参数出现的地方都应该加上括号,并且在整个宏定义的两边也加上括号

54:避免使用 #define 宏创建一种新语言

55:采用命名约定,使程序员很容易看出某个标识符是否为 #define 宏

56:只要合适就应该使用文件包含,不比担心它的额外开销

57:头文件只应该包含一组函数和(或)数据的声明

58:把不同集合的声明分离到不同的头文件中可以改善信息隐藏

59:嵌套的 #include 文件使我们很难判断源文件之间的依赖关系

60:在可能出现错误的场合,检查并报告错误

61:操纵文本行而无需顾及它们的外部标识形式,这个能力有助于提高程序的可移植性

62:使用 scanf 限定提高可移植性

63:当你打印长整数时,即使你所使用的机器并不需要,坚持使用 1 修改符可以提高可移植性

64:滥用 setjmp 和 longjmp 可能导致晦涩难懂的代码

65:对信号进行处理将导致程序的可移植性变差

66:使用断言可以简化程序的调试

67:避免使用具有副作用的函数可以使程序更容易理解

68:一个模块的接口应该避免暴漏它的细节

69:将数据类型参数化,是它更容易修改

70:只有模块对外公布的接口才应该是公用的71:使用断言来防止非法操作

72:几个不同的实现使用同一个通用接口是模块具有更强的可互换性

73:复用现存的代码而不是对它进行改写

74:迭代比尾部递归效率更高

75使用 stdarg 实现可变参数列表

76:改进算法比优化代码更有效率

77:使用某种环境特有的技巧会导致程序不可移植

篇6:C、C++程序员求职面

解答:

BOOL型变量:if(!var)

int型变量: if(var==0)

float型变量:

const float EPSINON = 0.00001;

if((x >=steps;char tmp[MAX_LEN];

strcpy(tmp, pStr + n);

strcpy(tmp + steps, pStr);

*(tmp + strlen(pStr))= ';strcpy(pStr, tmp);}

正确解答2:

void LoopMove(char *pStr, int steps){ int n = strlen(pStr)-steps;char tmp[MAX_LEN];

memcpy(tmp, pStr + n, steps);

memcpy(pStr + steps, pStr, n);

memcpy(pStr, tmp, steps);}

剖析:

这个试题主要考查面试者对标准库函数的熟练程度,在需要的时候引用库函数可以很大程度上简化程序编写的工作量。

最频繁被使用的库函数包括:

(1)strcpy

(2)memcpy

(3)memset

试题6:已知WAV文件格式如下表,打开一个WAV文件,以适当的数据结构组织WAV文件头并解析WAV格式的各项信息。

WAVE文件格式说明表

偏移地址 字节数 数据类型 内 容

文件头

00H 4 Char “RIFF”标志

04H 4 int32 文件长度

08H 4 Char “WAVE”标志

0CH 4 Char “fmt”标志

10H 4

过渡字节(不定)

14H 2 int16 格式类别

16H 2 int16 通道数

18H 2 int16 采样率(每秒样本数),表示每个通道的播放速度

1CH 4 int32 波形音频数据传送速率

20H 2 int16 数据块的调整数(按字节算的)

22H 2

每样本的数据位数

24H 4 Char 数据标记符"data"

28H 4 int32 语音数据的长度

解答:

将WAV文件格式定义为结构体WAVEFORMAT:

typedef struct tagWaveFormat {

char cRiffFlag[4];

UIN32 nFileLen;

char cWaveFlag[4];

char cFmtFlag[4];

char cTransition[4];

UIN16 nFormatTag;

UIN16 nChannels;

UIN16 nSamplesPerSec;

UIN32 nAvgBytesperSec;

UIN16 nBlockAlign;

UIN16 nBitNumPerSample;

char cDataFlag[4];

UIN16 nAudioLength;

} WAVEFORMAT;

假设WAV文件内容读出后存放在指针buffer开始的内存单元内,则分析文件格式的代码很简单,为:

WAVEFORMAT waveFormat;memcpy(&waveFormat, buffer,sizeof(WAVEFORMAT));

直接通过访问waveFormat的成员,就可以获得特定WAV文件的各项格式信息。

剖析:

试题6考查面试者组织数据结构的能力,有经验的程序设计者将属于一个整体的数据成员组织为一个结构体,利用指针类型转换,可以将memcpy、memset等函数直接用于结构体地址,进行结构体的整体操作。透过这个题可以看出面试者的程序设计经验是否丰富。

试题7:编写类String的构造函数、析构函数和赋值函数,已知类String的原型为:

class String {

public:

String(const char *str = NULL);// 普通构造函数

String(const String &other);// 拷贝构造函数

~ String(void);// 析构函数

String & operate =(const String &other);// 赋值函数

private:

char *m_data;// 用于保存字符串

};

解答:

//普通构造函数

String::String(const char *str){ if(str==NULL)

{

m_data = new char[1];// 得分点:对空字符串自动申请存放结束标志'的空

//加分点:对m_data加NULL 判断

*m_data = ';

}

else {

int length = strlen(str);

m_data = new char[length+1];// 若能加 NULL 判断则更好

strcpy(m_data, str);

} }

// String的析构函数 String::~String(void){ delete [] m_data;// 或delete m_data;}

//拷贝构造函数

String::String(const String &other)

// 得分点:输入参数为const型 {

int length = strlen(other.m_data);

m_data = new char[length+1];

//加分点:对m_data加NULL 判断

strcpy(m_data, other.m_data);}

//赋值函数

String & String::operate =(const String &other)// 得分点:输入参数为const型 {

if(this == &other)

//得分点:检查自赋值

return *this;

delete [] m_data;

//得分点:释放原有的内存资源

int length = strlen(other.m_data);

m_data = new char[length+1];//加分点:对m_data加NULL 判断

strcpy(m_data, other.m_data);

return *this;

//得分点:返回本对象的引用 }

剖析:

能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!

在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求,也是《Effective C++》中特别强调的条款。

仔细学习这个类,特别注意加注释的得分点和加分点的意义,这样就具备了60%以上的C++基本功!

试题8:请说出static和const关键字尽可能多的作用

解答:

static关键字至少有下列n个作用:

(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;

(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;

(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;

(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;

(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。

const关键字至少有下列n个作用:

(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;

(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;

(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;

(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;

(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。例如:

const classA operator*(const classA& a1,const classA& a2);

operator*的返回结果必须是一个const对象。如果不是,这样的变态代码也不会编译出错:

classA a, b, c;(a * b)= c;// 对a*b的结果赋值

操作(a * b)= c显然不符合编程者的初衷,也没有任何意义。

剖析:

惊讶吗?小小的static和const居然有这么多功能,我们能回答几个?如果只能回答1~2个,那还真得闭关再好好修炼修炼。

这个题可以考查面试者对程序设计知识的掌握程度是初级、中级还是比较深入,没有一定的知识广度和深度,不可能对这个问题给出全面的解答。大多数人只能回答出static和const关键字的部分功能。

4.技巧题

试题1:请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1

解答:

int checkCPU(){ {

union w

{

int a;

char b;

} c;

c.a = 1;

return(c.b == 1);} }

剖析:

嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为: 内存地址 存放内容

0x4000 0x34 0x4001 0x12

而在Big-endian模式CPU内存中的存放方式则为:

内存地址 存放内容

0x4000 0x12 0x4001 0x34

32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为: 内存地址 存放内容

0x4000 0x78 0x4001 0x56 0x4002 0x34 0x4003 0x12

而在Big-endian模式CPU内存中的存放方式则为:

内存地址 存放内容 0x4000 0x12 0x4001 0x34 0x4002 0x56 0x4003 0x78

联合体union的存放顺序是所有成员都从低地址开始存放,面试者的解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。如果谁能当场给出这个解答,那简直就是一个天才的程序员。

试题2:写一个函数返回1+2+3+„+n的值(假定结果不会超过长整型变量的范围)

解答:

int Sum(int n){

return((long)1 + n)* n / 2;

//或return(1l + n)* n / 2;}

剖析:

对于这个题,只能说,也许最简单的答案就是最好的答案。下面的解答,或者基于下面的解答思路去优化,不管怎么“折腾”,其效率也不可能与直接return(1 l + n)* n / 2相比!

int Sum(int n){ long sum = 0;for(int i=1;i<=n;i++){

sum += i;} return sum;}

所以程序员们需要敏感地将数学等知识用在程序设计中。

本篇文章来源于:开发学院 http://edu.codepub.com

篇7:C语言C++程序员编程必备

c与c++程序连接问题 它们之间的连接问题主要是因为c c++编绎器对函数名译码的方式不同所引起的……

考虑下面两个函数 /* c*/ int strlen(char* string) { ... } //c++ int strlen(char* string) { ... } 两个函数完全一样。在c在函数是通过函数名来识别的,而在C++中,由于存在函数的重载问题,函数的识别方式通函数名,函数的返回类型,函数参数列表三者组合来完成的,

因此上面两个相同的函数,经过C,C++编绎后会产生完全不同的名字。所以,如果把一个用c编绎器编绎的目标代码和一个用C++编绎器编绎的目标代码进行连接,就会出现连接失败的错误。 解决的方法是使用extern C,避免C++编绎器按照C++的方式去编绎C函数 在头文件中定义: extern “C” int strlen(char* string) 或 extern “C” { int strlen(char* string) } 当C编绎器遇到extern “C”的时候就用传统的C函数编译方法对该函数进行编译。由于C编绎器不认识extern “C”这个编绎指令,而程序员又希望C,C++程序能共用这个头文件,因此通常在头文件中使用_cplusplus宏进行区分: #if define _cplusplus extern “C”{ #endif int strlen(char* string) #ifdefine _cplusplus } #endif虽然很基础,但是解释透彻!

上一篇:班级班委职责下一篇:难忘我母校