C语言学习笔记必看知识点_第1页
C语言学习笔记必看知识点_第2页
C语言学习笔记必看知识点_第3页
C语言学习笔记必看知识点_第4页
C语言学习笔记必看知识点_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、C学习笔记 -必看知识点100例(上) -edited by lvlv from Nov. 8,2013 to Mar. 31,20141. define和ifndef的用法答:取消宏定义undef条件编译预处理:#ifndef 标识符 # define 标识符 程序段 1 #else 程序段 2 #endif 它的作用是当 “ 标识符 没有由# d e f i n e定义过。 则编译“程序段 1”。否则编译“程序段 2” 。注意:条件编译的作用是防止此头文件被多个文件调用,产生编译冲突,这里的表示符为当前头文件名的大写前加上_,如果头文件名为err.h,则标示符为_ERR_H.2. exte

2、rn关键字的用法。extern可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。 另外,extern也可用来进行链接指定。3. sizeof的结果等于对象或者类型所占的内存字节数。 4. snprintf()函数的用法。答:函数原型int snprintf(char *str, size_t size, const char *format, .);功能将可变个参数(.)按照format格式化成字符串,然后将其复制到str中。返回欲写入的字符串长度,若出错则返回负值。5. volatile(不稳定的,易变的)关键字答:volati

3、le i=10; k=i;volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 6. strtok函数的用法。答:函数原型char *strtok(char s, const char *delim);例如:strtok("abc,def,ghi",","),最后可以分割成为abc def ghi.尤其在点分十进制的IP中提取应用较多。7.MIC?答:英特尔集成众核(Intel Many Integrated Core,MIC)架构是英特尔公司现有产品(包括英

4、特尔至强处理器在内)的另一个关键补充。这种架构能在一颗芯片里面支持200多个线程同时工作。MIC众核协处理器Knight Corner,和之前上代Larrabee继承者Knights Ferry不同的是,新的Knights Corner从外表上看是采用与Xeon类似的LGA/BGA封装。从这点来看,集成50个x86核心,运算能力达到1TFLOPS的Knights Corner可能会放弃“加速卡”的形式,采用QPI总线替代PCI-E界面。7. C语言中函数指针变量的详细介绍答:函数指针变量的作用:指向函数入口地址,用来调用函数。使用函数指针的好处在于,可以将实现同一功能的多个模块统一起来标识,这

5、样一来更容易后期的维护,系统结构更加清晰。或者归纳为:便于分层设计、利于系统抽象、降低耦合度以及使接口与实现分开。函数指针变量定义的一般形式为:类型说明符 (* 指针变量名 )();其中 " 类型说明符 " 表示被指函数的返回值的类型。 "(* 指针变量名 )" 表示 "*" 后面的变量是定义的指针变量。 最后的空括号表示指针变量所指的是一个函数。例如申明函数指针变量:int (*pf)()或者char * (*pf)();后者表示 pf 是一个指向函数入口的指针变量,该函数的返回值 ( 函数值 ) 是指针型,指向字符串。使用方法:i

6、nt max(int x,int y)pf=函数名; (*pf)(int x,int y);8.conio.h头文件的说明答:conio.h不是C标准库中的头文件,在C standard library,ISO C 和POSIX标准中均没有定义。conio是Console Input/Output(控制台输入输出)的简写,其中定义了通过控制台进行数据输入和数据输出的函数,主要是一些用户通过按键盘产生的对应操作,比如getch()函数等等。大部分DOS,Windows 3.x,Phar Lap,DOSX,OS/2 or Win32平台上的C编译器提供此文件,UNIX 和Linux平台的c编译器通

7、常不包含此头文件。如果需要使用此头文件,可以从互联网下载。conio库不仅适用于 Windows 平台,在 Linux 下也可使用.网上已经有兼容包,下载后打开就可使用;而至于 Mac 则完全跟 Windows 没有区别,直接可以使用.9. +i和i+的效率的比较。答:简单的比较前缀自增运算符和后缀自增运算符的效率是片面的,因为存在很多因素影响这个问题的答案。以现在的编译器的优化水平,在内建数据类型的情况下,效率没有区别。在自定义数据类型的情况下,+i的效率较高。10.C语言中near和far关键字的作用?答:far是和near对应的,就是一般程序的函数调用都在64k地址范围内的,就是16位寻

8、址就够了,但是当代码比较庞大时,16位就可能不够了.far就代表32位寻址,函数的本质就是个地址,指针的本质也是个地址,所以就有了寻址的问题。11.头文件中stdlib.h内容。答:stdlib.h里面定义了五种类型、一些宏和通用工具函数。 类型例如size_t、wchar_t、div_t、ldiv_t和lldiv_t; 宏例如EXIT_FAILURE、EXIT_SUCCESS、RAND_MAX和MB_CUR_MAX等等; 常用的函数如malloc()、calloc()、realloc()、free()、system()、atoi()、atol()、rand()、srand()、exit()等

9、等。12. #define只有宏名定义是什么意思!答: 一般来说这样空的宏都是为了某些手段的,例如跨平台,比如说在windows下我让a赋值为10,在linux下要让a赋值为20,那么就可以这么写#ifdef WINDOWSa = 10;#endif#ifdef LINUXa = 20;#endif;这样我只要在某个地方定义一个#define WINDOWS或者#define LINUX就可以在跨平台的情况下采取不同的策略了.#undef 是在后面取消以前定义的宏定义18. extern “C”修饰符的理解!答:被extern "C"修饰的变量和函数是按照C语言方式编译和连

10、接的;19.C+中增加函数重载的功能的内部原理!答:C语言是不支持函数重载功能的,void foo( int x, int y );该函数被C编译器编译后在符号库中的名字为_foo,而C+编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C+就是靠这种机制来实现函数重载的。20.理解C、C+和C#中变量生存期的区别!答:应该从作用域的角度来区分变量的生存周期,生存周期分为三种:整个程序:修饰的关键字有static当前文

11、件(.c、.cpp、.cs文件):修饰的关键字有:C语言:auto(自动变量),C+语言:private、protected、public等,C#中:private、protected、public、partial等。当前程序段(if语句段、函数体等):修饰的关键字有:同当前文件注:函数体外定义静态变量为全局静态变量,函数体内定义静态变量为局部静态变量,二者生存周期都是整个程序。且C语言中没有私有和公有之分,C+扩充了这一个功能。21.引用和指针的区别?答:1.从内存上来讲 系统为指针分配内存空间,而引用与绑定的对象共享内存空间,系统不为引用变量分配内容空间。2指针初始化以后可以改变指向的对象

12、,而引用定义的时候必须要初始化,且初始化以后不允许再重新绑定对象。3.所以引用访问对象是直接访问。指针访问对象是间接访问。4。如果pa是指针,那么*pa就是引用了。又如int a,&ra= a;那么ra就是a的reference了。22. c语言中头文件、库文件和.c文件的联系与区别。答:h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的。附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件。如果要完成源代码的编译和链接,有头文件和lib就够了。如果也使动态连接的程序运行起来,有dll就够了。在开发和调试阶段,当然最好都有。23.C语言中编译链接

13、的过程!答:obj文件是目标文件,一般是程序编译后的二进制文件,在通过链接器和资源文件链接就成exe文件了。 OBJ只给出了程序的相对地址,而EXE是绝对地址。 OBJ文件不支持有孔的多边形面。24.常见字符编码有:ASCII编码(American Standard Code for Information Interchange)基本的 ASCII 字符集共有 128 个字符,包括常用的字母、数字、标点符号等,一个字节来存放一个 ASCII 字符。BIG-5码:是通行于台湾、香港地区的一个繁体字编码方案,俗称“大五码”。GB2312编码:对ASCII编码的扩充,收录简体中文和常用字符,通用于

14、中国大陆。每个汉字占用两个字节。基本集共收入汉字6763个和非汉字图形字符682个。对于人名、古汉语等方面出现的罕用字,GB 2312不能处理,这导致了后来GBK及GB 18030汉字字符集的出现。GBK编码:对GB2312的扩充,收录了繁体中文,简、繁体字融于一库,每个汉字占用两个字节。Unicode编码:注意,Unicode只是一个编码规范,目前实际实现的unicode编码只要有三种:UTF-8,UCS-2和UTF-16。Unicode当然是一个很大的集合,现在的规模可以容纳100多万个符号。Unicode固然统一了编码方式,但是它的效率不高,比如UCS-4(Unicode的标准之一)规定

15、用4个字节存储一个符号,那么每个英文字母前都必然有三个字节是0,这对存储和传输来说都很耗资源。UTF-8编码:UTF-8是一种8位的unicode字符集,编码长度是可变的,并且是ASCII字符集的严格超集,也就是说ASCII中每个字符的编码在UTF-8中 是完全一样的。UTF-8字符集中,一个字符可能是1个字节,2个字节,3个字节或者4个字节长。一般来说,欧洲的字母字符长度为1到2个字节,而亚洲的 大部分字符则是3个字节,附加字符为4个字节长。UCS-2编码:UCS-2是固定长度为16位的unicode字符集。每个字符都是2个字节,UCS-2只支持unicode3.0,所以不支持附加字符。UC

16、S-2的优点: 对于亚洲字符的存储空间需求比UTF-8少,因为每个字符都是2个字节。 处理字符的速度比UTF-8更快,因为是固定长度编码的。 对于windows和java的支持更好。UTF-16编码:UTF-16也是一种16位编码的字符集。实际上,UTF-16就是UCS-2加上附加字符的支持,也就是符合unicode4.0规范的UCS-2。所以UTF-16是UCS-2的严格超集。UTF-16中的字符,要么是2个字节,要么是4个字节表示的。UTF-16主要在windows2000以上版本使用。UTF-16相对UTF-8的优点,和UCS-2是一致的。总结:在亚洲进行在web开发时,面向的是全球,使

17、用UTF-8编码是绝对没有错的,面向亚洲的话,使用UCS-2和UTF编码效率会更高。综上所述,使用UTF-8编码绝对没有错,不会出现编码乱码的现象。25.Sql Sever 中char、varchar、nchar和nvarchar的对比区别!答:ncahr和nvarchar采用unicode编码,固定每个字符占用两个字节,char和varchar固定每个字符采用一个字节。所以一般来说,如果含有中文字符,用nchar/nvarchar,如果纯英文和数字,用char/varchar我把他们的区别概括成:CHAR,NCHAR 定长,速度快,占空间大,需处理VARCHAR,NVARCHAR,TEXT

18、不定长,空间小,速度慢,无需处理。注意:操作系统的语言环境支持中文可以使用char和varchar,如果操作系统环境不支持中文,必须使用nvarchar和ncahr。请协调好存储代价和兼容性之间的关系。26. MD5利用salt进行加密的过程程?用户输入【账号】和【密码】(以及其他用户信息); 系统为用户生成【Salt值】; 系统将【Salt值】和【用户密码】连接到一起; 对连接后的值进行散列,得到【Hash值】; 将【Hash值1】和【Salt值】分别放到数据库中。 用户登录时,用户输入【账号】和【密码】; 系统通过用户名找到与之对应的【Hash值】和【Salt值】; 系统将【Salt值】和

19、【用户输入的密码】连接到一起; 对连接后的值进行散列,得到【Hash值2】(注意是即时运算出来的值); 比较【Hash值1】和【Hash值2】是否相等,相等则表示密码正确,否则表示密码错误。 有时候,为了减轻开发压力,程序员会统一使用一个salt值(储存在某个地方),而不是每个用户都生成私有的salt值。27.MD5简介!答:Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现算法原

20、理:对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后单目运算符28.C语言中运算符的优先级别!30. alloca ,malloc、calloc和realloc的理解!答:alloca ()是分配在栈上,calloc()”是”分配内存给多个对象”,” malloc()”是”分配内存给一个对象”,”realloc()”是”重新分配内存”之意。”free()”就比较简单了,”释放”的意思,就是把之前所分配的内存空间给释放出来。参数均为以字节为单位。注意:allo

21、ca不具可移植性,而且在没有传统堆栈的机器上很难实现。当它的返回值直接传入另一个函数时会带来问题,因为他分配在栈上。 31.strstr(char *str1, char *str2)和strchr(const char *s,char c)的分别和用法!答:是分别求字符串和字符在前面字符串中第一次出现的地址的指针,指针的内容就是地址,返回的地址是字符串在内存中随机分配的地址再加上你所搜索的字符在字符串位置,如果s中不存在c则返回NULL。32. strcpy和memcpy主要有以下3方面的区别。1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型

22、、结构体、类等。2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。33.函数指针的用法答:函数指针的定义:/ 申明函数指针pfint (*pf)(const int&, const int&); / 具体函数int intCompare(const int& aInt, const int& bInt)可将函数指针pf指向函数intComparepf

23、= intCompare; 调用:/ 使用pfif(pf(aInt, bInt) = 0)cout << "two integers are equal" << "." << endl;或者用pf来申明其他的函数指针:/ 定义函数指针类型cmpFuntypedef int (*cmpFun)(const int&, const int&);cmpFun pf= intCompare;表示:pf指向函数intCompare();/函数名可以作为参数,申明形式是函数指针作为参数,其做法为int plusFu

24、n(int& aInt, int(*paf2)(const int&, const int&)int bInt = 1;int cInt = 2;return aInt + paf2(bInt, cInt);函数指针作为返回值一个函数的返回值可以是一个函数指针,这个声明形式写起来有点麻烦:/ 函数指针作为返回值int (*retFunPointer(int)(const int&, const int&);上面的声明的含义:a)       retFunPointer是一个函数,该函数有一个in

25、t类型的参数;b)       retFunPointer返回值是一个函数指针,它指向的是带有两个const int&类型参数,且返回类型为int的函数。 retFunPointer的定义:/ 函数指针为返回值,整个函数名为retFunPointer,把自己装扮成函数指针,作为返回值。int (*retFunPointer(int aInt)(const int&, const int&)cout << aInt << endl;/ pf已经在前面定义过了return pf;调

26、用代码示例:/ 函数指针作为返回值,retFunPointer返回一个cmpFun类型的函数指针cmpFun pf3 = retFunPointer(aaInt);int result = pf3(aaInt, bbInt);cout << result << endl;34.注意:答:C语言中,头文件中include的头文件内申明的函数,在当前.c文件中,是可以间接调用的!35.注意答:C语言中没有bool类型,用0和1来表示真假!C语言和C+都是强类型的,变量在申明时候就要指定类型,而不是等编译器根据编译时候所赋的值来确定其便编译时的类型。36. MD5算法原理简介

27、!答:对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。也就是32个十六进制的字符,每个字符占4位从0到f,均为小写,因此叫做128位散列值。37. strncmp()函数简介答:用 法: int strncmp(char *str1, char *str2, int maxlen);说明:此函数功能即比较字符串str1和str2的前maxlen个字符。如果前maxlen字节完全相等,返回值就=0;在前maxlen字节比较过程中,如果

28、出现str1n与str2n不等,则返回(str1n-str2n)1。38. <<和>>和>>>这三个运算符号的理解答:<<(左移)运算规则:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。数学意义:在数字没有溢出的前提下,对于正数和负数,左移一位都相当于乘以2的1次方,左移n位就相当于乘以2的n次方。>>(带符号右移)运算规则:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1。数学意义:右移一位相当于除2,右移n位相当于除以2的n次方。这里是取商

29、哈,余数就不要了。>>>(无符号右移)运算规则:按二进制形式把所有的数字向右移动对应位数,低位移出(舍弃),高位的空位补零。对于正数来说和带符号右移相同,对于负数来说不同。 其他结构和>>相似。39.getch()函数和getchar()函数的区别答:getch():所在头文件:conio.h函数用途:从控制台读取一个字符,但不显示在屏幕上,然后程序继续执行下去。getchar()函数:所在头文件时stdio.h函数用途:用户按下字符后,等待用户按下回车,然后继续执行,且返回值显示在屏幕上。40.注意strlen()函数求字符串长度的时候不会讲结尾符号0算进去。s

30、ubstr()函数是C+中的函数,C语言中没有这个函数,要想实现这个功能,可以使用strncpy()或者memcpy来实现。41. strncpy()和memcpy()的区别答:二者都可指定长度来实现串的拷贝。不同点是当然有区别,strncpy()时拷贝字符串,memcpy()是拷贝内存内容,可以拷贝其他类型的数据。42. sizeof()函数答:sizeof是运算符,可用于任何变量名、类型名或常量值,当用于变量名(不是数组名)或常量时,它不需要用圆括号。它在编译时起作用,而不是运行时。sizeof的结果等于对象或者类型所占的内存字节数,包括字符串的结尾符0,strlen()求字符串的长度不包

31、括结尾符0。43. memet()函数,解决内存内存空间出现屯屯屯屯屯屯和烫烫烫烫烫烫乱码答:void *memset(void *s, char ch, size_t n);将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向S的指针。其中void *s空指针,指针不指向任何地址空间。初始化内存地址空间后就会解决乱码问题,用memset(s,NULL,sizeof(s).乱码问题是因为使用malloc()申请的内存空间没有初始化,默认赋值0xcc,打印出来就是屯屯屯,malloc申请的空

32、间是在"堆"上的,可手动释放。使用alloca()申请内存会产生烫烫烫烫烫烫,与malloc,calloc,realloc类似,但是注意一个重要的区别,_alloca是在栈(stack)上申请空间,用完马上就释放,无需手动释放。44. c语言中定义变量不赋初值默认是多少?答:C语言中,没有加static 默认为auto 型此时不给初值的变量的初值是随机的,但是 如果加了 static,不给初值的变量的初值是默认是0,指针也是一样,其实 NULL 的值就是0,只是它不代表任何地址。45.C语言从源码到可执行程序的四个过程答: 预处理(也称预编译,Preprocessing):

33、C语言的预处理主要有三个方面的内容: 1.宏定义; 2.文件包含; 3.条件编译。 预处理命令以符号“#”开头,这个方面本质是将需要的代码包含到当前的.c文件中。编译(Compilation):编译所做的工作就是词法分析,语法分析,在进行汇编成中间代码,汇编代码。汇编(Assembly):汇编实际上指把汇编语言代码翻译成目标机器指令的过程。经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。目标文件由段组成。通常一个目标文件中至少有两个段:代码段:该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。数据段:主要存放程序中要用到的各种

34、全局变量或静态的数据。一般数据段都是可读,可写,可执行的。链接(Linking):链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。链接过程分为静态链接和动态链接。静态链接是指连接程序从静态链接库中拷贝需要的代码到被执行的程序中,动态链接是指代码被放到称作是动态链接库或共享对象的某个目标文件中,链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态

35、链接程序将根据可执行程序中记录的信息找到相应的函数代码。 46.GCC编译器编译的过程答:实质上,GCC的编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(Linking)。一步到位编译:gcc test.c -o test.out 输出可执行文件test.out预处理:gcc -E test.c -o test.i 或 gcc -E test.c编译为汇编代码(Compilation):gcc -S test.i -o test.s汇编(Assembly):gcc -c test.s

36、-o test.o,编译成目标文件test.o。连接(Linking):gcc test.o -o test.out47. C语言程序调试的常见错误分析与解决办法答:C语言程序的编译是以.c文件为单位进行编译的,生成.obj二进制目标文件,最后在链接成可执行文件。编译提示的错误:编译的时候进行词法分析和语法分析,此时书写不符合语法规则或者未定义会进行报错,这种错误容易处理。链接提示的错误:经常会出现某函数已经在main.obj文件中定义,出现重复编译。这时候预处理的条件编译就发挥作用了,可以防止重复编译。但是,作用只能是防止变量的申明的重复编译,而不能防止变量的定义的重复编译。也就是说,在头文

37、件中定义了函数之后,在不同的.c文件引入头文件中,两个.c文件生成的obj文件中都会含有对函数体代码的目标代码。原因是,我个人理解是,条件编译之所以对头文件中定义的函数不能起到防止重复编译的功能,是因为函数体的实现代码编译后最终是要存入obj目标文件中的,编译是 以.c文件为单位的,每个.c文件都会被编译成.obj文件,但是.h文件中不能编译成obj文件,因此其函数的定义部分,即实现部分一定要编译成目标代 码存入obj文件,供链接时使用。但是当两个.c文件同时引用头文件时,两个.c文件都可包含函数实现部分的代码的目标代码,编译器没有规定将函数代码的 目标代码存入哪个.c文件,只能两个同时包含,

38、这就导致了链接时出现的重复定义的问题。解决的办法就是不要在头文件中定义变量,只能申明。或者只能让一 个.c文件引用含有定义变量的头文件,或者用static来修饰函数,定义为全局静态类型函数,这样的话函数代码就会被存到全局/静态存储区,编译时只会被编译一次,若非static静态全局变量,函数被包含进.c文件后,就变成了当前.c文件的全局变量,而不是整个程序的全局变量,这就导致了每个.c文件把它当做自己的函数来进行编译,将目标代码存入自己的obj文件中,链接时就会出错。 48.C/C+语言中程序在内存中的分区情况答:在C+中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储

39、区。 栈区,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。 堆区,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。  程序代码区存放函数体的二进制代码。   全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C+里面没有这个区分了,他们共同占用同一块内存区。 常量存储区,这是一块比较特殊的存储区,他们里面存放的

40、是常量,不允许修改50.C语言中sizeof()不能用来求指针指向的内存空间的大小答:*output=(char *)alloca(23*sizeof(char);sizeof(output);求得的不是指针output指向的内存的地址空间的大小,而是指针变量本身所占的内存空间大小,为4个字节。指针和数组是不一样的,但数组做为参数传递时就会退化为同类型的指针. str是数组拥有固定的内存 sizeof是计算它占的字节数,而指针只是一个存放变量地址的一个变量 在任何时候都是占四个字节.51.C 语言中不能用用strlen(),来求指针指向内存空间的长度,初始化后的指针字符串才

41、可以答:因为strlen()函数是用来计算字符串的长度,是以NULL来表示的字符串结尾的标志,如果没有0这个字符的话,strlen()统计出来的长度是不正确的。52. C语言中函数的变参问题答:C语言中输入和输出格式控制函数的参数实现不定的变化,其实现的机理是因为VA_LIST,是在C语言中解决变参问题的一组宏,所在头文件:#include <stdarg.h>。具体请参见百度百科。53.8086/8088处理器中段的首地址,基址和偏移地址从哪获取答:物理地址段基址*16+偏移地址段的首地址就是段的基地址,等于段寄存器的内容*16。段寄存器分为CS(代码段,Code Segment

42、)、DS(数据段,Data Segment)、SS(堆栈段,Stack Segment)和ES(附加段数据,Extra Segment)寄存器。当进行读/写存储器操作数或者访问变量时,自动选择DS或者ES寄存器作为段基址。DS偏移地址对应SI(Source Index源变址寄存器)、DI(Destination Index目的变址寄存器)CS偏移地址对应IP(指针寄存器)SS偏移地址对应BP(基址指针寄存器Base Pointer)或SP(堆栈指针寄存器Stack Pointer)ES偏移地址对应 DI(Destination Index目的变址寄存器) 53.C语言中地址寻址与处理器的关系答

43、:8080的地址线是16条,8086/8088的地址线有20条,80286的地址线有24条,Intel 80386 微处理器提供了32位地址总线,Intel 80386 微处理器内存管理的三种工作方式 有三种:实地址方式,虚地址保护方式,虚拟8086方式。 实地址模式:寻址采用和8086相同的16位段和偏移量,最大寻址空间1MB,最大分段64KB。可以使用32位指令。32位的x86 CPU用做高速的8086。保护模式:寻址采用32位段和偏移量,最大寻址空间4GB,最大分段4GB (Pentium Pre及以后为64GB)。虚拟8086

44、方式:在保护模式下CPU可以进入虚拟8086方式,这是在保护模式下的实模式程序运行环境。54.操作系统内存分段管理和分页管理的区别答:页和分段系统有许多相似之处,但在概念上两者完全不同,主要表现在:1、页是信息的物理单位,分页是为实现离散分配方式,以消减内存的外零头,提高内存的 利用率;或者说,分页仅仅是由于系统管理的需要,而不是用户的需要。段是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了能更好的满足 用户的需要。2、页的大小固定且由系统确定,把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而一个系统只能有一种大小的页面。段的长度却 不固定,决定于用户所编写的程

45、序,通常由编辑程序在对源程序进行编辑时,根据信息的性质来划分。3、分页的作业地址空间是维一的,即单一的线性空间,程序 员只须利用一个记忆符,即可表示一地址。分段的作业地址空间是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。55.C语言程序中常量会经常出现后面有个u,这表示什么答:13u,0xffu,283u,这在C语言中表示定义变量时的后缀,u表示整型无符号数。56.exit()函数答:所在头文件:stdlib.h功 能: 关闭所有文件,终止正在执行的程序。exit(1)表示异常退出,exit(x)(x不为0)都表示异常退出。57.对于内存空间分配函数alloca、mallo

46、c、calloc、realloc的理解答:他们返回的是指向开辟空间的void型指针,故需要强制类型转换为需要的指针类型。如:float *p=(float *)malloc(100*sizeof(float);即申请一个指向100个float型数据的指针,即float指针p。注意:void型指针可以强制转换为其他类型的指针,并且其他类型的指针都可自动转换为void型指针。58C语言中的格式化函数答:fprintf()函数:fprintf是C/C+中的一个格式化写库函数;其作用是格式化输出到一个流/文件中。sscanf()函数:从一个字符串中读进与指定格式相符的数据。sscanf与scanf类似

47、,都是用于输入的,只是后者以键盘(stdin)为输入源,前者以固定字符串为输入源。sprintf()函数:字串格式化命令,主要功能是把格式化的数据写入某个字符串中。sprintf 是个变参函数。sscanf()和sprintf()函数的区别:sscanf的作用是字符串转换成字符,sprintf()函数是字符转换成字符串。示例:十六进制字符串穿转换为ASCII字符串到dst中int v;for (i=0; i<16; i+) sscanf(result+i*2,"%2x",&v); /dsti=(char)(v&0xFFu);/ 0xFFu表示无符号十六

48、进制数,作用取余 把ASCII字符串转换成十六进制字符串到result中 for (i=0; i<16; i+)sprintf(result+2*i, "%02x", digesti);result32=0;59. C语言程序在VS2008编译时候出现的奇怪的错误答:(1)error C2099: 初始值设定项不是常量,原因是C语言编译器不允许变量申明在函数外,解决办法是申明在函数内。(2)异常代码是:char *inputstr="8e7b27b2f9c02c7fe5687c66751f046100000000a6f9ba4e"inputstri

49、 =d;未处理的异常: 0xC0000005: 写入位置 0x0135674c 时发生访问冲突。分析:产生这种异常的原因是字符指针inputstr指向的是常量,该常量存放在内存的常量区,不允许修改,故抛出这种异常。解决办法:不要对常量区的成员进行值的更改。应该放在堆栈区进行操作。(3)C语言中在编译的时候有时会出现error C2143: 语法错误: 缺少“;”(在“类型”的前面),但我们用24K钛合金狗眼找了七七49分钟,都没有发现哪有少;这个符号,事实上,这是VS编译器欺骗了我们,因为VS编译器规定变量的声明必须放在函数内开始的部分,不能放在其他非变量申明语句的后面。(4)错误:Run-T

50、ime Check Failure #2 - Stack around the variable 'v' was corrupted.错误代码:char v;for (i=0; i<16; i+) sscanf(result+i*2,"%2x",&v);解决办法:将char v改为int v,这种导致栈损坏应该是十六进制格式写入char类型变量的时候发生的,但是还不知道为什么会这样。60. 常见排序算法答.插入排序法:1简单插入排序法 2希尔排序法 选择排序法:1简单选择排序 2堆排序 交换排序:1 冒泡排序 2 快速排序冒泡排序:(Bubbl

51、e Sort)它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。具体代码演示请见百度百科。为稳定排序。快速排序:(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。为不稳定排序。简单插入排序法:比如如下示例1 5 7 3 1 6把表分成

52、两部分,前半部分已排序,后半部分未排序,我用|分开初始为 5 | 1 7 3 1 6一次插入排序,把第一个1插入前边已排序部分,得1 5 | 7 3 1 6后边依次是1 5 7 | 3 1 61 3 5 7 | 1 61 1 3 5 7 | 61 1 3 5 6 7 |为稳定排序。希尔排序:(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序,因DLShell于1959年提出而得名。希尔排序的基本思想是:将需要排序的序列划分成为d个较小的子序列,所有距离为d的倍数的记录放在同一个序列中。然后对子序列进行插入排序,通过插入排序能够使得原来序列基本有序。这

53、样通过对较小的序列进行插入排序,然后对基本有序的数列进行插入排序,能够提高插入排序算法的效率。增量d的选取原则:去上一个增量的一般作为此次序列的划分增量。为不稳定排序。简单选择排序: 设所排序序列的记录个数为n。i取1,2,n-1,从所有n-i+1个记录(Ri,Ri+1,Rn)中找出排序码最小的记录,与第i个记录交换。执行n-1趟 后就完成了记录序列的排序。为不稳定排序。堆排序:61.C语言跟内存分配方式(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在

54、栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(3)从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等.其中alloca是向栈申请内存,因此无需释放. malloc分配的内存是位于堆中的,并且没有初始化内存的内容,因此基本上malloc之后,调用函数memset来初始

55、化这部分的内存空间.calloc则将初始化这部分的内存,设置为0. 而realloc则对malloc申请的内存进行大小的调整.申请的内存最终需要通过函数free来释放. 而sbrk则是增加数据段的大小。62 C语言中数据类型转换原则答:数据类型转换分为显示转换和隐式转换。显示转换属于强制类型转换,隐式转换属于自动转换。 高到低的顺序给各种数据类型分等级,依次为:long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int 和int,char。这是按照数据类型的表示范围大小

56、来划分的。 数据类型转换存在两种场合:一是在赋值语句中,会进行转换,高等级数据类型会进行截断或舍入操作。低等级数据类型会完整的转换为高等级数据。二是在运算表达式中,低等级数据类型会自动向高等级数据类型转换,被转换成表示范围更大的类型,故而把这种转换称为“升级(promotion)”。注意:char类型可以自动转换为int类型。char类型变量在内存中的存储是以一个字节的ASCII码值来存放的,会被自动转换为int型。当字符串转换为int型时,也是读取ASCII码值。比如字符串”aaaa”转换为unsigned int时,因为在VS开发环境下,unsigned int占四个字节,这与我们有些C教

57、科书上说的占两个字节不同。字符a的ASCII码值对应的是97,二进制表示是01100001,那么字符串”aaaa”63.堆和栈的定性理解问题是:堆与栈到底是什么,是指一块内存区呢,还是指一种数据结构?答:明确说明操作系统(或编译原理)的堆与栈和数据结构的堆与栈是不同的概念。OS(Operating System)中的堆栈指的是两块相邻的存储空间,数据结构中的堆和栈指的是不同的数据结构。堆是完全二叉树,按性质是分为大顶堆或小顶堆,即父节点大于或小于左右孩子,通常用来排序或者进行。栈的性质则是先进后出,通常用在临时存储局部结果上。64.CLR与程序集的关系与区别答:程序集:经由编译器编译得到的,供CLR进一步编译执行的那个中间产物,在WINDOWS系统中,它一般表现为。dll,或者是。exe的格式,但是要注意,它们跟普通意义上的WIN32可执行程序是完全不同的东西,程序集必须依靠CLR才能顺利执行。 CLR: Common Language Runtime, 公共语言运行时, 是一个可由多种编程语言使用的运行环境。CLR的核心功能包括:内存管理、程序集加载、安全性、异常处理和线程同步,可由面向CLR的所有语言使用。并保

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论