C++学习(27)

1.   下述代码 str1str2地址不同,p1p2地址不同。

str1str2值不同,p1p2值相同。

const char str1[]="abc";

const char str2[]="abc";

const char *p1="abc";

const char *p2="abc";

 

2.定义网络传输数据包为

class packet{

      int size;

void data[0];

}

其中data的作用是:维护数据包空间的连续性。

分析:

1.data[0]表示柔性数组,是为了减少内存碎片保持属于连续性,连续的地址并非是独立的地址空间

2.该数组的内存地址就和它后面的元素地址相同,意味着无需初始化,数组名就是后面元素的地址,直接就能当指针使用。例如,制作动态buffer,可以这样分配空间malloc(sizeof(structXXX) + buff_len); 直接就把buffer的结构体和缓冲区一块分配了。这样使用释放一次即可,如果使用指针,则需要释放两次。

3.考虑到可移植性的原因,可以写成data[1]data[],因为有些编译器不支持0数组。

 

关于柔性数组进一步学习:点击打开链接

 

3.多个源文件组成的C程序,经过编辑,预处理,编译,链接等阶段会生成最终的可执行程序。下面哪个阶段可以发现被调用的函数未定义C

A.      预处理

B.      编译

C.       链接

D.      执行

 

分析一:

A预处理是 C语言程序从源代码变成可执行程序的第一步,主要是 C语言编译器对各种预处理命令进行处理,包括头文件的包含、宏定义的扩展、条件编译的选择等。

 

B编译之前,C语言编译器会进行词法分析、语法分析 (-fsyntax-only),接着会把源代码翻译成中间语言,即汇编语言。编译程序工作时,先分析,后综合,从而得到目标程序。所谓分析,是指词法分析和语法分析;所谓综合是指代码优化,存储分配和代码生成。值得一提的是,大多数的编译程序直接产生机器语言的目标代码,形成可执行的目标文件,但也有的编译程序则先产生汇编语言一级的符号代码文件,然后再调用汇编程序进行翻译加工处理,最后产生可执行的机器语言目标文件。 

 

C链接是处理可重定位文件,把它们的各种符号引用和符号定义转换为可执行文件中的合适信息(一般是虚拟内存地址 )的过程。

 

分析二:

//预处理:处理#include、宏替换和条件编译

//编译:生成目标文件(.cpp->.o

//链接:链接多个目标文件

//例子: main.cpp

int main() {

 fun();

}

//编译不可通过,提示函数fun()未声明

void fun();

int main() {

fun();

} //编译可通过,链接不可通过,提示函数fun()未定义

 

4.32位机器代码上,根据以下代码:

signed char a=0xe0;

unsigned int b=a;

unsigned char c=a;

A a>0 &&c>0为真           Ba==c为真

C b的十六进制表示0xffffffe0      D上面都不对

分析:

同等位数的类型之间的赋值表达式不会改变其在内存之中的表现形式,因此通过 unsigned char c = a;语句,c的位存储形式还是0xe0

 

对于B选项,编译器首先检查关系表达式"=="左右两边a ,c的类型,如果某个类型是比int的位宽小的类型,就会先进行Integer Promotion,将其提升为int类型,至于提升的方法,是先根据原始类型进行位扩展(如果原始类型为unsigned ,进行零扩展,如果原始类型为signed,进行符号位扩展)32位,再根据需要进行unsigned to int 形式的转换。

因此:asigned char型,位宽比int小,执行符号位扩展,被提升为 0xffffffe0;cunsigned char型,位宽比int小,执行零扩展,被提升为 0x000000e0;经过以上步骤,再对两边进行比较,显然发现左右是不同的,因此==表达式值为false

再举一个例子:

-------------------------------------

signed int a =0xe0000000

unsigned int b = a;

cout<< (b ==a) <<endl;

-------------------------------------

结果为 1,因为ab位宽已经达到了int的位宽,均不需要Integer Promotion,只需要对a执行从unsigned to signed的转换,然而这并不影响其在内存中的表现形式,因此和b比较起来结果为真。

 

5.mallocfree属于函数,newdelete属于运算符。

sizeof是操作符;

补充:’.’ ‘’ ‘ ::’ ‘?!’ ‘sizeof’这五个运算符不可以重载。

 

6.以下定义错误的是(A

Astruct A(A_a);        B.struct A(A* _a);         C.struct A(A&_a); D.struct B; structA{B& _b;}; struct B{A&_a;};

分析: struct成员类型不可以是它自己。因为会递归定义。理论上这样导致结构体的大小不能被计算(无限大小)。所以不能在结构体里的成员类型是结构体本身。但是成员可以定义为该结构体的指针。就像你上面这段代码。因为指针的大小是已知的(随编译器和操作系统而定)。所以可以定义为该结构体的指针,但不是该结构体。

 

7.下述哪个代码是正确的?(C

A. int f() {int*a=new int(3);return *a;}

B int *f() {inta[3]={1,2,3}return a;}

C vector <int>f(){vector<int>v(3);return v;}

D void f(int*ret){int a[3]={1,2,3};ret=a;return;}

 

A存在内存泄露,没有delete

B数组是临时的,根本传不到主调函数中。

C vector在堆上分配内存。

D错在函数参数传入的是指针,只会改变指针所指向的内容,而指针本身是不会改变的。

 

B想返回数组却返回了一个临时空间()上的数组,D也是如此,妄想通过ret改变指针实参的指向,很明显达不到效果应该使用二级指针,并且妄想指向的空间还是个临时空间,D错的一塌糊涂。

补充:D正确的做法是把形参改成**ret,并且函数内给数组在堆上分配空间,再让ret去指,这时候实参才能真正传出想要的内存空间。

 

8.假设下面函数foo会被多线程调用,那么让i,j,k三个变量哪些因为线程间共享访问需要加锁保护(ij

int i=0;

void foo() {

      static int j=0;

int k=0;

i++;j++;k++;

}

分析:多线程调用时要进行保护时,主要是针对全局变量和静态变量的,函数内的局部变量不会受到影响这里i是全局变量,j是局部静态变量,i和j都有可能被多线程同时访问,所以需要保护;而k是栈里的变量,只能被该时刻的函数体所使用,所以不用保护。

每个线程都有一个栈,保存自己的局部变量;多线程需要程序员考虑全局变量和静态变量的保护。线程内的局部变量是该线程多独有的,是不会被共享的,自然不需要保护。

 

9this指针保证每个对象拥有自己的数据成员,但共享处理这些数据的代码。相同类型的对象共用同一段实现代码,所以需要this指针区分对象与对象间的差异。

This就是当前对象的引用。

 

10.linux编程中,以下哪个TCP的套接字选项与nagle算法的开启和关闭有关?B

A TCP_MAXSEG      B TCP_NODELAY    

C TCP_SYNCNT       D TCP_KEEPPALIVE

分析:Nagle算法的规则:

1)如果包长度达到MSS,则允许发送;

2)如果该包含有FIN,则允许发送;

3设置了TCP_NODELAY选项,则允许发送;

4)未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送;

5)上述条件都未满足,但发生了超时(一般为200ms),则立即发送。

 

Nagle算法只允许一个未被ACK的包存在于网络,它并不管包的大小,因此它事实上就是一个扩展的停-等协议,只不过它是基于包停-等的,而不是基于字节停-等的。Nagle算法完全由TCP协议的ACK机制决定,这会带来一些问题,比如如果对端ACK回复很快的话,Nagle事实上不会拼接太多的数据包,虽然避免了网络拥塞,网络总体的利用率依然很低。

 

Nagle算法是silly window syndrome(SWS)预防算法的一个半集。SWS算法预防发送少量的数据,Nagle算法是其在发送方的实现,而接收方要做的是不要通告缓冲空间的很小增长,不通知小窗口,除非缓冲区空间有显著的增长。这里显著的增长定义为完全大小的段(MSS)或增长到大于最大窗口的一半。

注意:BSD的实现是允许在空闲链接上发送大的写操作剩下的最后的小段,也就是说,当超过1MSS数据发送时,内核先依次发送完nMSS的数据包,然后再发送尾部的小数据包,其间不再延时等待。(假设网络不阻塞且接收窗口足够大)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值