精选面试题

文章目录

    • 三次握手
    • 迭代器失效
    • size_t 和 ptrdiff_t
    • native pointer,原生指针
    • 顶层const和底层const
    • 数组名不能自加操作,指针可以自加操作
    • memmove
    • strcpy ————仿照memmove()
    • operator++(int)
    • 左值和右值
    • 大端和小端

三次握手

赤壁之战中,孙刘联军包围了曹操,为歼灭曹贼,孙刘联军必须同时发起进攻形成包围圈。那么问题来了,如果诸葛亮准备于次日卯时借东风,怎么通知孙权进攻时间呢?

精选面试题_第1张图片

打电话?不可能,没有这个玩意儿。

派传令兵。可是必须进过曹军阵地,这样安全吗?

刘备的传令兵可能出现的情况:

1.顺利抵达
刘备派传令兵(去通知孙权)->孙权派传令兵(给刘备说我知道了)->刘备派传令兵(孙权我已经收到)
消灭曹军

2.没有到达,孙权没有收到信息
传令兵有可能:

  • 被曹军斥候发现抓走了
  • 迷路了
  • 被老虎吃了
  • 当逃兵跑了

等了好久也不接孙权回信, 刘备慌了,只好另派一名传令兵。

3.到达了,但信息损坏。

  • 路上下暴雨
  • 密信丢失
  • 被曹军斥候发现抓走,传令兵被严刑拷打,交出了密信,曹操将密信修改之后送往东吴大营

+++

孙权收到后起了疑心,这到底是不是刘备发送的,会不会让曹操改过了呢?遂又派一名传令兵将信送往刘备。为了不延误战机,隔了一个时辰,孙权又派了一个传令兵。

+++
刘备收到信后,发现卯时被改为子时,派骑兵通知孙权收到的信息是错的。以防万一,刘备又派了一名。

其中,一次完整的信息传达必定有三次正确的传令兵抵达,任何一次未到,都会导致密信的重新发送。

迭代器失效

int arr[]={1,2,3,4,5,6,7,8,9,10};
vectorvec(arr,arr+9);
vector::iterator iter=vec.begin();
for(;iter!=vec.end();iter++){
    if(*iter % 2 != 0){
        vec.eraser(iter);
    }
}
for(auto s : vec){//输出
    cout<

//改正

int arr[]={1,2,3,4,5,6,7,8,9,10};
vectorvec(arr,arr+9);
vector::iterator iter=vec.begin();
for(;iter!=vec.end();){
    if(*iter % 2 != 0){
        iter=vec.eraser(iter);
    }
    else{
        iter++;
    }
}
for(auto s : vec){//输出
    cout<

size_t 和 ptrdiff_t

定义与中 => C++
size_t:unsigned类型
ptrdiff_t:signed整型,用来保存两个指针减法操作

native pointer,原生指针

见C++11

顶层const和底层const

一个指针本身添加const限定符就是顶层const,而指针所指的对象添加const限定符就是底层const。

数组名不能自加操作,指针可以自加操作

1.char p[] = “ssd”;
++ p;
为什么会提示’++’ needs l-value ?

2.为什么
char *p = “ssd”;
++ p;
却可以呢???

原因:指针名类型 char* const p=…(指向不可变)
指针可以 + + 操作,而数组名也可以转化为指向第一个元素的指针,但是为什么数组名不能++操作呢?
因为定义了一个数组,那么这个数组的地址就是固定的了。如char p[] = “ssd”; 那么p的地址是固定的。相当于char *const类型。改变p的指向当然错了。

3.int arr[5];
arr+1 就是对 arr 的地址偏移 int个单位

memmove

#include 
#include 

void *memmove(void *dest,const void *src,size_t count)
{
    void *ret=dest;
    if(dest == NULL || src == NULL)
        return;
    //这里来判别dest和src是否是指向同一字符串中不同位置,
    //如果是指向同一字符串,但是dest在src前面,则可以从前往后逐个赋值
    //如果是指向同一字符串,但是dest在src后面,且dest>=src+count,那么仍然从前往后赋值
    if(dest<=src||dest>=src+count)
    {
        while(count--)
            *dest++=*src++;
            /*可合并为while((*dest++ = *src++) != '\0');*/
    }
    //如果是指向同一字符串,但是dest在src后面,且dest<=src+count,那么从后往前赋值
    else
    {
        dest+=count-1;
        src+=count-1;
        while(count--)
            *dest--=*src--;
    }
    return ret;
}

int main()
{
    char s[]="Golden Global View";
/*    
    //这个用来测试dest在src的前面
    memmove(s,s+7,strlen(s)-7);
    s[strlen(s)-7]=0;
    printf("%s",s);
    
    printf("/n/n");
*/
    //这个用来测试dest在src的后面,但是dest<=src+count
    memmove(s+7,s,strlen(s)-7);
    s[strlen(s)-7]=0;
    printf("%s",s);

    getchar();
    return 0;
}


strcpy ————仿照memmove()

char *strcpy(char *dest,const char *src)
{
    char *ret=dest;
    if(dest == NULL || src == NULL)
        return;
    //这里来判别dest和src是否是指向同一字符串中不同位置,
    //如果是指向同一字符串,但是dest在src前面,则可以从前往后逐个赋值
    //如果是指向同一字符串,但是dest在src后面,且dest>=src+count,那么仍然从前往后赋值
    
    int count=0;
    char* tmp=src;//用来找src的长度
    while(*tmp!='\0'){
        count++;
    }
    
    if(dest<=src||dest>=src+count)
    {
        while(count--)
            *dest++=*src++;
            /*可合并为while((*dest++ = *src++) != '\0');*/
    }
    //如果是指向同一字符串,但是dest在src后面,且dest<=src+count,那么从后往前赋值
    else
    {
        dest+=count-1;
        src+=count-1;
        while(count--)
            *dest--=*src--;
    }
    return ret;
}

operator++(int)

int& int::operator++() //返回一个引用形式。函数返回值也可以作为一个左值使用
{//函数本身无参,意味着是在自身空间内增加1的
  *this += 1;  // 增加
  return *this;  // 取回值
}

const int int::operator++(int) //函数返回值是一个非左值型的,与前缀形式的差别所在。
{//函数带参,说明有另外的空间开辟
  int oldValue = *this;  // 取回值
  ++(*this);  // 增加
  return oldValue;  // 返回被取回的值
}

左值和右值

L-value中的L指的是Location,表示可寻址。Avalue (computer science)that has an address.
R-value中的R指的是Read,表示可读。in computer science, a value that does not have an address in a computer language.

/*左值和右值是相对于赋值表达式而言的。
左值是能出现在赋值表达式左边的表达式。左值表达式可以分为可读写的左值和只读左值。
右值是可以出现在赋值表达式右边的表达式,他可以是不占据内存空间的临时量或字面量,可以是不具有写入权的空间实体。
如*/
int a=3;
const int b=5;
a=b+2; //a是左值,b+2是右值
b=a+2; //错!b是只读的左值但无写入权,不能出现在赋值符号左边
34=a+2; //错!34是字面量不能做左值

大端和小端

网络传输时是一位一位传输的,所以100M的单位是bit,而网线是8根线,用户接受到数据时为字节byte。1byte=8bits。

1.大端存储:
网络传输的时候,想要边读边处理,没必要等四次凑齐(按int对齐)之后再做转换,这样效率高。

2.小端存储:
为了方便数据转换,比如int和short型互相转换等等(在计算机内部,这种转换是非常多得,大部分时间都消耗于此),为了高效,采取小端。

你可能感兴趣的:(C,C++)