CC++面试题

    技术2025-11-10  8

    1.写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值     int a = 4;     (A)a += (a++); (B) a += (++a) ;(C) (a++) += a;(D) (++a) += (a++);     a = ? 答:C错误,左侧不是一个有效变量,不能赋值,可改为(++a) += a; 改后答案依次为9,10,10,11 2.32位系统下, C++程序,请计算sizeof 的值    char str[] = “http://www.ibegroup.com/”     char *p = str ;     int n = 10;     请计算     sizeof (str ) = à17    sizeof ( p ) = à 4    sizeof ( n ) = à 4    void Foo ( char str[100])

    {         //请计算         sizeof( str ) = à 4    } void *p = malloc( 100 ); 请计算 sizeof ( p ) = à 43. 回答下面的问题.(1).头文件中的 ifndef/define/endif 干什么用?预处理     答:防止头文件被重复引用 (2). #include #include “filename.h” 有什么区别?     答:前者用来包含开发环境提供的库头文件,后者用来包含自己编写的头文件。 (3).C++ 程序中调用被 C 编译器编译后的函数,为什么要加 extern “C”声明?     答:函数和变量被C++编译后在符号库中的名字与C语言的不同,被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。由于编译后的名字不同,C++程序不能直接调 C 函数。C++提供了一个C 连接交换指定符号extern“C”来解决这个问题。 (4). switch()中不允许的数据类型是?     答:实型 4. 回答下面的问题(1).Void GetMemory(char **p, int num)

    {

    *p = (char *)malloc(num);

    }

    void Test(void)

    { char *str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str);

    }

    请问运行Test 函数会有什么样的结果?

    (2)char *GetMemory(void)

    {

             char p[] = "hello world";

             return p;

    }

     

    void Test(void)

    {

             char *str = NULL;

             str = GetMemory();

             printf(str);    

    }

    RetMenory执行完毕,p资源被回收,指向未知地址。返回地址,str的内容应是不可预测的, 打印的应该是str的地址

    void getmemory(char *p)             {                    p=(char *) malloc(100);                    strcpy(p,"hello world");                        int main( )             {                    char *str=NULL;                    getmemory(str);                    printf("%s/n",str);                    free(str);                    return 0;             }程序崩溃,getmemory中的malloc 不能返回动态内存, free()对str操作很危险

    5不调用C++/C 的字符串库函数,请编写函数 strcat char * __cdecl strcat (char * dst, const char * src) {     char * cp = dst;     while( *cp )     cp++; /* find end of dst */     while( *cp++ = *src++ ) ; /* Copy src to end of dst */     return( dst ); /* return dst */ }

    6 C++中什么数据分配在栈或堆中,New分配数据是在近堆还是远堆中? 答:栈: 存放局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理 : 程序运行时动态申请,new 和 malloc申请的内存就在堆上

    7 static有什么用途?(请至少说明两种)     1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。     2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。     3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用 8 .引用与指针有什么区别?     1) 引用必须被初始化,指针不必。     2) 引用初始化以后不能被改变,指针可以改变所指的对象。     3) 不存在指向空值的引用,但是存在指向空值的指针。

    9什么函数不能声明为虚函数?       constructor函数不能声明为虚函数。

    10.不能做switch()的参数类型是:          switch的参数不能为实型。

    11 static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?     答:全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。     从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。     static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件     static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;     static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;     static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

    12 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

             #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL

    我在这想看到几件事情:

    1) #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)

    2)懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。

    3) 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。

    4) 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。

     

    13 . 写一个"标准"MIN ,这个宏输入两个参数并返回较小的一个。

            #define MIN(A,B) ((A <= (B) ? (A) : (B))

    这个测试是为下面的目的而设的:

    1) 标识#define在宏中应用的基本知识。这是很重要的。因为在  嵌入(inline)操作符 变为标准C的一部分之前,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。

    2)三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。

    3) 懂得在宏中小心地把参数用括号括起来

    4) 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?

            least = MIN(*p++, b);

    14. 用变量a给出下面的定义

    a) 一个整型数(An integer

    b)一个指向整型数的指针( A pointer to an integer

    c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an integer

    d)一个有10个整型数的数组( An array of 10 integers

    e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers

    f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers

    g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数答案是:

    a) int a; // An integer

    b) int *a; // A pointer to an integer

    c) int **a; // A pointer to a pointer to an integer

    d) int a[10]; // An array of 10 integers

    e) int *a[10]; // An array of 10 pointers to integers

    f) int (*a)[10]; // A pointer to an array of 10 integers

    g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer

    h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer

    15. 关键字static的作用是什么?

    这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:

    1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

    2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

    3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

    16.关键字const有什么含意?

    const int a;

    int const a;

    const int *a;

    int * const a;

    int const * a const;

     

    /******/

    前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。顺带提一句,也许你可能会问,即使不用关键字 const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:

    1) 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。

    2) 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。

    3) 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

    访问固定的内存位置(Accessing fixed memory locations

     

    17. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。

    这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:

        int *ptr;

        ptr = (int *)0x67a9;

        *ptr = 0xaa55;

    一个较晦涩的方法是:

        *(int * const)(0x67a9) = 0xaa55;

    即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。

     

    18 . 下面的代码输出是什么,为什么?

    void foo(void)

    {

        unsigned int a = 6;

        int b = -20;

        (a+b > 6) ? puts("> 6") : puts("<= 6");

    }

    这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 ">6"。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6

     

    19 Typedef C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:

    #define dPS struct s *

    typedef struct s * tPS;

    以上两种情况的意图都是要定义dPS tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?

    dPS p1,p2;

    tPS p3,p4;

    第一个扩展为

    struct s * p1, p2;

    上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 p4 两个指针。晦涩的语法

     

    20、上述三个有什么区别?

    char * const p; //常量指针,p的值不可以修改

    char const * p//指向常量的指针,指向的常量值不可以改

    const char *p //char const *p

     

    char str1[] = "abc";

    char str2[] = "abc";

    const char str3[] = "abc";

    const char str4[] = "abc";

     

    const char *str5 = "abc";

    const char *str6 = "abc";

    char *str7 = "abc";

    char *str8 = "abc";

     

    cout << ( str1 == str2 ) << endl;

    cout << ( str3 == str4 ) << endl;

    cout << ( str5 == str6 ) << endl;

    cout << ( str7 == str8 ) << endl;

    结果是:0 0 1 1

    解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间;

    str5,str6,str7,str8是指针,它们指向相同的常量区域。

     

    21、一个strcpy函数考察的问题

            char * strcpy(char * strDest,const char * strSrc);

        1.不调用库函数,实现strcpy函数。

        2.解释为什么要返回char *

        解说:

        1.strcpy的实现代码

            char * strcpy(char * strDest,const char * strSrc)

            {

                    if ((strDest==NULL)||(strSrc==NULL)) file://[/1]

                            throw "Invalid argument(s)"; //[2]

                    char * strDestCopy=strDest;  file://[/3]

                    while ((*strDest++=*strSrc++)!='/0'); file://[/4]

                    return strDestCopy;

            }

        错误的做法:

        [1]

        (A)不检查指针的有效性,说明答题者不注重代码的健壮性。

        (B)检查指针的有效性时使用((!strDest)||(!strSrc))(!(strDest&&strSrc)),说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了booltruefalse三个关键字以提供更安全的条件表达式。

        (C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好处。直接使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。

        [2]

        (A)return new string("Invalid argument(s)");,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。

        (B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。

        [3]

        (A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。

        [4]

        (A)循环写成while (*strDest++=*strSrc++);,同[1](B)

        (B)循环写成while (*strSrc!='/0') *strDest++=*strSrc++;,说明答题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上'/0'

     

    22int main()   {    int x=3;    printf("%d",x);    return 1;      }问函数既然不会被其它函数调用,为什么要返回1mian中,c标准认为0表示成功,非0表示错误。具体的值是某中具体出错信息

     

    23.cc++中的struct有什么不同?cc++struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++structclass的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private

    24.交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3;有两种解法, 一种用算术算法, 一种用^(异或)a = a + b;b = a - b;a = a - b;

    另一种方法是:a = a^b;// 只能对int,char..b = a^b;a = a^b;ora ^= b ^= a;

    25、写一个标准宏,这个宏输入两个参数并返回较小的一个。.   #define Min(X, Y) ((X)>(Y)?(Y):(X))              //结尾没有;,注意括号

     

    26 关于内存对齐的问题以及sizof()的输出 答:编译器自动对齐的原因:为了提高程序的性能,数据结构(尤其是栈)应该尽可能

    地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问。

    然而,对齐的内存访问仅需要一次访问。

     

    最新回复(0)