//////////////////////////////////////////////////////////////////////// /* 以下有关C语言的说法中,错误的是________。 正确答案: D 你的答案: D (正确) a内存泄露一般是指程序申请了一块内存,使用完后,没有及时将这块内存释放,从而导致程序占用大量内存。 b无法通过malloc(size_t)函数调用申请超过该机器物理内存大小的内存块。 c无法通过内存释放函数free(void*)直接将某块已经使用完的物理内存直接还给操作系统。 d可以通过内存分配函数malloc(size_t)直接申请物理内存。 内存泄漏也称作“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。 (其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。 free释放的内存不一定直接还给操作系统,可能要到进程结束才释放。 可以直到malloc不能直接申请物理内存,它申请的是虚拟内存 */ //////////////////////////////////////////////////////////////////////// /* #include <iostream> using namespace std; class A { public: void print() { cout << "A:print()"; } }; class B: private A { public: void print() { cout << "B:print()"; } }; class C: public B { public: void print() { A:: print(); } }; int main() { C b; b.print(); } 正确答案: C 你的答案: C (正确) A:print() B:print() 编译出错 B的继承为私有继承,对于C已经不能再调用A的所有方法了 */ //////////////////////////////////////////////////////////////////////// /* 是一个行列数均为1000二维数组,下面代码效率执行最高的是() 正确答案: D 你的答案: D (正确) for(int j=0;j<1000;j++) for(int i=0;i<1000;i++) x[i][j]+=x[j][i]; for(int i=0;i<1000;j++) for(int j=0;j<1000;j++) x[i][j]+=x[j][i]; for(int i=0;i<1000;j++) for(int j=0;j<1000;j++) x[j][i]+=x[j][i]; for(int i=0;i<1000;i++) for(int j=0;j<1000;j++) x[i][j]+=x[i][j]; 主要是考察了CPU cache的预取操作,数组x[1000][1000]在内存中,是按行进行存储。 D选项外部循环是按行进行,因此操作第i行时,会将第i行后面的部分数预取到cache中,操作速度最快。 ABC选项其中都有跳列的操作,不能发挥cache的预取操作功能。 */ //////////////////////////////////////////////////////////////////////// /* 面向对象的程序设计语言具有()等共同特性。 正确答案: A B E 你的答案: A B E (正确) 封装性 多态性 简单性 复杂性 继承性 */ //////////////////////////////////////////////////////////////////////// /* 运行下面这段C语言程序之后,输出在屏幕上的结果是: void foobar(int a, int *b, int **c) { int *p = &a; *p = 101; *c = b; b = p; } int main() { int a = 1; int b = 2; int c = 3; int *p = &c; foobar(a, &b, &p); printf("a=%d, b=%d, c=%d, *p=%d\n", a, b, c, *p); return (0); } 正确答案: A a=1, b=2, c=3, *p=2 a=101, b=2, c=3, *p=2 a=101, b=101, c=2, *p=3 a=1, b=101, c=2, *p=3 1函数foobar中的a是按值传递,因此在函数中的修改不会引起主函数中的变化。 2函数中b传递的是主函数中b的指针,语句b = p ,其中p指向的是函数foobar内局部变量a的地址, 让传递过去的指针换了指向的数据,原来指向的数据(主函数中的b)不会有影响。如果这里是*b = *p那么主函数中的b也要相应变化。 3函数中的c传递的是双重指针,*c = b,也就是让主函数中的p指针指向了主函数中的b的地址 4在函数foobar中对指针的变化没有影响到主函数,只是让双重指针更换了指向而已 */ //////////////////////////////////////////////////////////////////////// /* 下面哪些属于使用"常引用"的原因? 正确答案: A C 提高程序的效率 节省存储空间 保护传递给函数的数据不在函数中被改变 以上都不正确 */ //////////////////////////////////////////////////////////////////////// /* 在64位系统下,分别定义如下两个变量:char *p[10]; char(*p1)[10];请问,sizeof(p)和sizeof (p1)分别值为__80、8__。 */ //////////////////////////////////////////////////////////////////////// /* main 函数执行以前,还会执行什么代码? 正确答案: A 你 全局对象的构造函数 全局对象的析构函数 局部对象的构造函数 局部对象的析构函数 */ //////////////////////////////////////////////////////////////////////// /* 若有一下程序 #include <stdio.h> main(){ int a=-11,b=10; a/=b/=-4; printf("%d %d\n",a,B); } 则程序的输出结果是? 正确答案: C 你的答案: C (正确) 4 -3 -1 -2 5 -2 5 -3 */ //////////////////////////////////////////////////////////////////////// /* 在一个双向循环链表中,指针p所指向的节点(非尾节点)之后插入指针s指向的节点,其修改指针的操作是 正确答案: E A p->next=s; s->prev=p; p->next->prev=s; s->next=p->next; B p->next->prev=s; p->next=s; s->prev=p; s->next=p->next; C p->next->prev=s; s->prev=p; p->next=s; s->next=p->next; D s->prev=p; s->next=p->next; p->next=s; p->next->prev=s ; E s->prev=p; s->next=p->next; p->next->prev=s; p->next=s; F s->next =p->next;s->prev=p; p->next=s;p->next->prev=s; 答案A,B,C都先断开了链表,导致后续(或前续)节点丢失 答案D和F中的p->next=s;在更新s->next之前,导致原链表中p->next丢失 */ //////////////////////////////////////////////////////////////////////// /* 32位机上根据下面的代码,问哪些说法是正确的? signed char a = 0xe0; unsigned int b = a; unsigned char c = a; 正确答案: C 你的答案: B (错误) A a>0 && c>0 为真 B a == c 为真 C b 的十六进制表示是:0xffffffe0 D 上面都不对 同等位数的类型之间的赋值表达式不会改变其在内存之中的表现形式,因此通过 unsigned char c = a;语句,c的位存储形式还是0xe0 对于B选项,编译器首先检查关系表达式"==" 左右两边a ,c的类型,如果某个类型是比int的位宽小的类型, 就会先进行Integer Promotion,将其提升为int类型,至于提升的方法, 是先根据原始类型进行位扩展(如果原始类型为unsigned ,进行零扩展,如果原始类型为signed,进行符号位扩展)至32位, 再根据需要进行unsigned to int 形式的转换。 因此: a 为signed char 型,位宽比int小,执行符号位扩展,被提升为 0xffffffe0; c 为unsigned char型,位宽比int小,执行零扩展,被提升为 0x000000e0; 经过以上步骤,再对两边进行比较,显然发现左右是不同的,因此==表达式值为false。 再举一个例子: ------------------------------------- signed int a = 0xe0000000 unsigned int b = a; cout<< (b == a) <<endl; ------------------------------------- 结果为 1, 因为a、b位宽已经达到了int的位宽,均不需要Integer Promotion,只需要对a执行从unsigned to signed的转换,然而这并不影响其在内存中的表现形式,因此和b比较起来结果为真。 */ //////////////////////////////////////////////////////////////////////// /* 声明常量时通常会用关键字const和static,下面关于两者的区别说法正确的是? 正确答案: B C A static表示这个变量可以在其他文件中使用 B static变量连接期被分配到了data段,即使是在函数调用中定义也不会在栈中产生,而是在程序加载期就被加入了内存 C const表面含义是个常量,但实际上还是占据一个内存位置的变量,但是它的值一般实在编译时期就决定了 D 上面说法都不正确 */ //////////////////////////////////////////////////////////////////////// /* 函数func的定义如下: 1 2 3 4 5 void func(const int& v1, cont int& v2) { std::cout << v1 << ' '; std::cout << v2 << ' '; } 在Visual Studio开发环境下, 以下代码输出结果为____。 int main (int argc, char* argv[]) { int i=0; func(++i,i++); return 0; } 正确答案: D 你的答案: D (正确) A0 1 B1 2 C2 1 D2 0 E0 2 F1 0 C语言函数参数入栈顺序为由右向左,func(++i, i++)可以分解为 参数 i 先入栈 输出0 然后执行i++ 此时i为1 接着参数 i 先执行++i i 此时为2 后入栈进行输出 2 */ //////////////////////////////////////////////////////////////////////// /* 空类大小为1 深度探索c++对象模型中是这样说的:那是被编译器插进去的一个char ,使得这个class的不同实体(object)在内存中配置独一无二的地址。 也就是说这个char是用来标识类的不同对象的。 */ //////////////////////////////////////////////////////////////////////// /* 如果类的定义如下,则以下代码正确并且是良好编程风格的是: class Object { public: virtual ~Object() {} //… }; 正确答案: A 你的答案: A (正确) std::auto_ptr<Object> pObj(new Object); std::vector<std::auto_ptr<Object*> > object_vector; std::auto_ptr<Object*> pObj(new Object); std::vector<std::auto_ptr<Object> > object_vector; auto_ptr的几点注意事项: 1、auto_ptr不能共享所有权 2、auto_ptr不能指向数组 3、auto_ptr不能作为容器的成员 4、不能通过复制操作来初始化auto_ptr std::auto_ptr<int> p(new int(42)); //OK std::atuo_ptr<int>p = new int(42);//Error 这是因为auto_ptr的构造函数被定义了explicit 5、不要把auto_ptr放入容器 */ //////////////////////////////////////////////////////////////////////// /* 下面程序的输出结果是 1 2 3 char *p1= “123”, *p2 = “ABC”, str[50]= "xyz"; strcpy(str+2,strcat(p1,p2)); cout << str; 正确答案: D 你的答案: D (正确) xyz123ABC z123ABC xy123ABC 出错 分析:p1和p2指向的是常量存储区的字符串常量,没法连接,会有问题 char* a="12345"; char* b="1"; strcpy(a,b);//error cout<<a; char *c=new char[6]; strcpy(c,b);//ok cout<<c; */ //////////////////////////////////////////////////////////////////////// /* 下面程序运行后的结果为: char str[] = "glad to test something"; char *p = str; p++; int *p1 = reinterpret_cast<int *>(p); p1++; p = reinterpret_cast<char *>(p1); printf("result is %s\n", p); 正确答案: D 你的答案: D (正确) result is glad to test something result is ad to test something result is test something result is to test something p的类型为char *,p++后p指向str数组的第2个元素即字母“l”的位置。 p1的类型为int *,p1++后p1指向的位置增加4个字节,指向str数组中的第6个元素即字母“t”的位置。 因此最后p的内容为“to test something”。 此处用static_cast<> 要引入中介void* char str[] = "glad to test something"; char *p = str; p++; int *p1 = static_cast<int*> (static_cast<void*> (p)); p1++; p = static_cast<char*> (static_cast<void*> (p1)); printf("result is %s\n", p); */ //////////////////////////////////////////////////////////////////////// /* 以下程序用来统计文件中字符的个数 #include<stdio.h> main() { FILE *fp; long num=0; fp=fopen("fname.dat", "r" ); while (________) { fgetc( fp ); num++ ; } printf( " num= % d\n",num); fclose( fp ); } 下面选项中,填入横线处不能得到正确结果的是? 正确答案: B feof( fp )= =NULL ! feof( fp ) feof(fp) feof( fp ) == 0 函数feof 用以检查文件是否结束,结束是返回非零 */ //////////////////////////////////////////////////////////////////////// /* 若fp已定义为指向某文件的指针,且没有读到该文件的末尾,C语言函数feof( fp)的函数返回值是? 正确答案: D 你的答案: D (正确) EOF 非0 -1 0 feof函数的用法是从输入流读取数据,如果到达稳健末尾(遇文件结束符),eof函数值为非零值,否则为0 */ //////////////////////////////////////////////////////////////////////// /* 在一台主流配置的PC机上,调用f(35)所需的时间大概是_______。 int f(int x) { int s=0; while(x-- >0) s+=f(x); return max(s,1); } 正确答案: D 几毫秒 几秒 几分钟 几小时 计算执行次数得到递推公式 f(n)=f(n-1)+....+f(0) f(n)=2(f(n-2)+...+f(0)) f(n)=2^2(f(n-3)+...+f(0)) ... f(n)=2^(n-1)f(0)=2^(n-1) f(35)=2^34 大改100多亿 计算机应该是每秒几百万次 所以算下来需要几个小时 */ //////////////////////////////////////////////////////////////////////// /* 在 32 位操作系统中,下列类型占用 8 个字符的为______。 正确答案: D short int Int C long Unsigned int Long long Char Int */ //////////////////////////////////////////////////////////////////////// /* C中的结构体没有函数 但是C++的结构体可以有函数;这是C与C++结构体的区别。 C++的结构体可以被类取代,因为类相对于结构体 具有封装性等优势。 C++中结构体与类的区别: 结构体中的成员访问权限不声明时候默认是 公开的;而类 是私有的 */ //////////////////////////////////////////////////////////////////////// /* 下列关于多态性说法不正确的是( )。 正确答案: B 你的答案: B (正确) 多态性是指同名函数对应多种不同的实现 重载方式仅有函数重载 重载方式包含函数重载和运算符重载 多态性表现为静态和动态两种方式 C++中,实现多态有以下方法:虚函数,抽象类,覆盖,模板(重载和多态无关)。 */ //////////////////////////////////////////////////////////////////////// /* 在Linux 系统中,在运行一个程序时,程序中未初始化的全局变量会被加载到以下哪个内存段中? 正确答案: A 你的答案: A (正确) BSS TEXT DATA STACK BSS(Block Started by Symbol)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。 特点是:可读写的,在程序执行之前BSS段会自动清0。所以,未初始的全局变量在程序执行之前已经成0了。 数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。 代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。 这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。 在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。 堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。 当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张); 当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减) 栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量 (但不包括static声明的变量,static意味着在数据段中存放变量)。 除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中, 并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点, 所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区 全局的未初始化变量存在于.bss段中,具体体现为一个占位符;全局的已初始化变量存于.data段中; 而函数内的自动变量都在栈上分配空间。.bss是不占用.exe文件空间的,其内容由操作系统初始化(清零); 而.data却需要占用,其内容由程序初始化,因此造成了上述情况。 bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小。 data(已手动初始化的数据)段则为数据分配空间,数据保存在目标文件中。 数据段包含经过初始化的全局变量以及它们的值。BSS段的大小从可执行文件中得到 , 然后链接器得到这个大小的内存块,紧跟在数据段后面。当这个内存区进入程序的地址空间后全部清零。 包含数据段和BSS段的整个区段此时通常称为数据区。 */ //////////////////////////////////////////////////////////////////////// /* 在异常处理中,入释放资源,关闭数据库、关闭文件应由( )语句来完成。 正确答案: C 你的答案: C (正确) try子句 catch子句 finally子句 throw子句 try-finally语句是Microsoft对C和C++语言的扩展,它能使32位的目标程序在异常出现时, 有效保证一些资源能够被及时清除,这些资源的清除任务可以包括例如内存的释放,文件的关闭,文件句柄的释放等等。 */ //////////////////////////////////////////////////////////////////////// /* void fut(int**s,int p[2][3]) { **s=p[1][1]; } void main( ) { int a[2][3]={1,3,5,7,9,11},*p; p=(int*)malloc(sizeof(int)); fut(&p,a); cout<< *p; } 正确答案: B 你的答案: B (正确) 7 9 1 11 */ //////////////////////////////////////////////////////////////////////// /* int (*p)[3] p的含义是什么? 正确答案: B 你的答案: B (正确) 一个指向int元素大小为3的指针数组 一个指向元素个数为3的int数组的指针 不合法 以上说法都不正确 */ //////////////////////////////////////////////////////////////////////// /* 不能把字符串"HELLO!"赋给数组b的语句是() 正确答案: B 你的答案: B (正确) char b[10]={'H','E','L','L','O','!','\0'}; char b[10];b="HELLO!"; char b[10];strcpy(b,"HELLO!"); char b[10]="HELLO!"; */ //////////////////////////////////////////////////////////////////////// /* 下面的函数哪个是系统调用而不是库函数()? 正确答案: D 你的答案: D (正确) printf scanf fgetc read print_s scan_s read()不是库函数,是系统调用,作用是读文件(Linux中的一切设备都看做文件) 函数原型: Ssize_t read(int filedes, void *buf, size_t nbytes); Returns:number of bytes read, 0 if end of file, -1 on error 如果read系统调用成功,则将返回读取到的字节数;如果遇到了文件尾EOF,则返回0。 */ //////////////////////////////////////////////////////////////////////// /* 有如下程序段: char fun(char *); main() { char *s = “one”, a[5] = {0}, (*f1)(char *) = fun, ch; } 则对函数fun的调用语句正确的是 正确答案: C D 你的答案: C D (正确) *f1(&a); f1(*s); f1(&ch) ch = *f1(s);要改成(*f1)(s)才正确 */ ////////////////////////////////////////////////////////////////////////