c++---面试题目大总结

来源:互联网 发布:软件专利说明书范文 编辑:程序博客网 时间:2024/04/28 11:40

1 类型转换

#include<iostream>
#include<stdio.h>
#include<assert.h>

using namespace std;

void test()
{
        float a = 1.0f;
        cout<< (int) a <<endl;
        cout<< &a<<endl;
        cout<< (int &)a<<endl;
        printf("f=%f\n",a);
        cout<< boolalpha << ((int)a == (int&)a)<<endl<<endl;

        float b = 0.0f;
        cout<< (int) b <<endl;
        cout<< &b<<endl;
        cout<< (int &)b<<endl;
        cout<< boolalpha << ((int)b == (int&)b)<<endl;
}

int main()
{
        cout<<"begin..."<<endl;
        test();
        cout<<"end..."<<endl;
}

结果

begin...
1
0xbf8dfcbc
1065353216
f=1.000000
false

0
0xbf8dfcb8
0
true
end...


float 在内存中的存储方式与int 不同



2  指针运算问题

void test()
{
        int arr[] = {6,7,8,9};
        int *p = arr;

        //*(p++) += 123;
        *p++ += 123;    // == *p = *p +123


        printf("%d\n",*p);
        printf("%d , %d \n",*p,*(++p)); // 从右到左运算
}

int main()
{
        cout<<"begin..."<<endl;
        test();
        cout<<"end..."<<endl;
}

结果

begin...
7
8 , 8
end...



3  指针强制类型转换


void test()
{
    int a = 10;
    printf("a=%08x\n",a);
    int *p = &a;
    //强制类型转换,有危险
    char *pp = (char*)p;
    printf("%08x\n",*pp);
    printf("%d\n",*pp);

    //高位被截取
    unsigned int aa = 0xfffffff7;
    unsigned char i = (unsigned char)aa;
    //强制类型转换,有危险
    char *b = (char*)&aa;
    
    printf("%08x, %08x\n",i,*b);
}


结果

begin...
a=0000000a
0000000a
10
000000f7, fffffff7
end...


指针可以强制转换,指针保存的是地址。


4  运算符优先级问题

void test()
{
    unsigned char a = 0xA5;
    
    // 先 ~a 后 4+1 再 a >>
    unsigned char b = ~a >> 4 + 1;
    //0xA5 在寄存器表达式为0000 0000 1010 0101
    //取反后 1111 1111 0101 1010
    // 右移5位 后 取低8位 1111 1010
    printf("%08x\n",b);
    printf("%016x\n",b);
    printf("%032x\n",b);
}

结果


begin...
000000fa
00000000000000fa
000000000000000000000000000000fa
end...


250



5  使用位运算实现加法

int add(int a, int b)
{
        if(b == 0 )
                return a;
        int sum,carry;
        sum = a^b;
        carry = (a & b) << 1;

        return add(sum,carry);
}

void test()
{
        int a = add(4,88);
        printf("%d\n",a);
}


6  指针与引用的区别

第一,非空区别。在任何情况下都不能使用指向空值的引用。一个引用必须总是指向某些对象。

因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,

因为这样你可以赋空值给该变量。相反,如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。

不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针要高。


第二,合法性区别。在使用引用之前不需要测试它的合法性。

相反,指针则是应该总是被测试,指针则应该总是被测试,防止其为空。


第三,可修改区别。指针与引用的另一个重要的区别是指针可以被重新赋值以指向另一个不同的对象。

但是引用则总是指向在初始化时被指定的对象,以后不能改变,但是指定的对象其内容可以改变。


第四,应用区别。总的来说,在以下情况下应该使用指针:

一是考虑到存在不指向任何对象的可能(在这种情况下,能够设置指针为空)

二是需要能够在不同的时刻指向不同的对象(在这种情况下,你能够改变指针的指向)。

如果总是指向一个对象并且一旦指向一个对象后就不会改变指向,那么应该使用引用 。


7  先调用父类构造函数

class A
{
        public:
                int a;
        A()
        {
                a = 1;
        }
        void print()
        {
                printf("%d\n",a);
        }
};


class B: public A
{
        public:
                int a;
        B()
        {
                a = 2;
        }
};


void test()
{
        B b;
        b.print();
        printf("%d\n",b.a);
}


8   c++ 有了malloc/free 为什么还要new/delete?

malloc与free是c++/c语言的标准库函数,new/delete是c++的运算符。它们都是用于申请动态内存和释放内存。

对于非内部数据类型的对象而言,只用malloc/free无法满足动态对象的要求。

对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。

由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free.

因此c++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete.

new/delete不是库函数,而是运算符。


9 一个类似于printf的函数,可以接受任意多个参数

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stdarg.h>

using namespace std;

void foo(char *fmt, ...)
{
    va_list ap;
    int d;
    char c, *s;

    va_start(ap, fmt);
    while (*fmt)
    switch (*fmt++)
    {
        case 's':              /* string */
            s = va_arg(ap, char *);
            printf("string %s\n", s);
            break;
        case 'd':              /* int */
            d = va_arg(ap, int);
            printf("int %d\n", d);
            break;
        case 'c':              /* char */
            c = (char) va_arg(ap, int);
            printf("char %c\n", c);
            break;
    }
    va_end(ap);
}

int myprint(const char* format,...)
{
    va_list ap;
    va_start(ap,format);
    
    const int size = strlen(format) +1 ;
    char* tmp = new char[size];
    memset(tmp,0,size);
    
    while(*format != 0)
    {
        int i;
        for(i=0;i<size && *format != '%' && *format != 0;i++)
        {
            tmp[i] = *format++;
        }
        tmp[i] = 0;    
        printf("tmp [%s]\n",tmp);    
        if(*format == 0)
            return 0;
        
        switch(*++format)
        {
            case 'd':    
            {
                printf("%d",(int)va_arg(ap,int));
                break;
            }
            case 's':    
            {
                printf("%s",(char*)va_arg(ap,char*));
                break;
            }
            case 'c':    
            {
                printf("%c",(char)va_arg(ap,int));
                break;
            }
            case 'f':    
            {
                printf("%f",(float)va_arg(ap,double));
                break;
            }
            case '%':    
            {
                printf("%%");
                break;
            }
            default:
            {
                printf("input error");
                return 1;
            }
       }
       ++format;
    
    }
    
    delete [] tmp;
    va_end(ap);
    return 0;    
}


void test()
{
    //foo("%c",48);    
    //myprint("%c-%d",48,1);
    //myprint("%%zyk%%zyk%%");
    myprint("\nzyk is a pretty boy! His age is %d and %s",5,"I love zyk^_^!");
    printf("\n");    
}

int main()
{
    test();
    return 0;
}

10 实现atoi函数

include<iostream>
#include<stdio.h>

using namespace std;


enum Status{kvalid =0,kinvalid};
int g_nstatus = kvalid;

int str_to_int(const char* str)
{
    g_nstatus = kinvalid;
    int num = 0;
    
    if(str != NULL)
    {
        const char* digit = str;
        
        bool minus = false;
        if(*digit == '+')
        {
                digit++;
        }
        else if(*digit == '-')
        {
            digit++;
            minus = true;
        }
        else if(*digit == '\0')
        {
            return num;
        }
        if(*digit != '\0')
        {
        while(*digit != '\0')
        {
            if(*digit >= '0' && *digit <= '9')
            {
                    num = num *10 + (*digit - '0');
                    digit++;
            }
            else
            {
                num = 0;
                return num;
            }
        }
        }
        else
        {
                return num;    
        }
        if(*digit == '\0')
        {
            g_nstatus = kvalid;
            if(minus)
                num = 0 - num;
        }
    }

    return num;        
}

void test()
{
    const char* str1 = "123";
    int num1 = str_to_int(str1);    
    printf("num1=[%d],g_nstatus=[%d]\n",num1,g_nstatus);

    const char* str2 = "-123";
    int num2 = str_to_int(str2);    
    printf("num2=[%d],g_nstatus=[%d]\n",num2,g_nstatus);
    
    //const char* str3 = "";
    //const char* str3 = "+";
    //const char* str3 = "+ ";
    const char* str3 = "+122";
    //const char* str3 = NULL;
    int num3 = str_to_int(str3);    
    printf("num3=[%d],g_nstatus=[%d]\n",num3,g_nstatus);

    //const char* str4 = "12a";
    //const char* str4 = "a1";
    const char* str4 = " 1";
    int num4 = str_to_int(str4);    
    printf("num4=[%d],g_nstatus=[%d]\n",num4,g_nstatus);
    
    
}


int main()
{
    test();
    return 0;
}