nowcoder 题解
字节对齐
- 结构体变量的首地址能够被器最宽基本类型的成员的大小整除
- 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍。
- 结构体的总大小最宽基本类型成员大小的整数倍,如有需要编译器会在最末尾一个成员之后加上填充字节。
struct T{
char a;
int *d;
int b;
int c:16;
double e;
};
T *p;
解析:a占一个字节,d在64位中占8个字节(32位 4个字节),p一样,
所以根据准则2,d的偏移量都是8的整数倍,所以d得地址为[8]-[15],b 占了4个字节,地址为[16][19],c指定为16,占了两个字节,地址为20 21,e占8字节。
大端存储 编译和体系结构
unsigned int a=0x1234;其中int是4个自己,大端存储,补齐16进制表示为:0x00 0012 34
unsigned char b=(unsigned char)&a; 由于大端存储,所以上述int a变量的最低地址存储的是 十六进制表示最左边的1个字节,为0x00.
void foo(int *a,int *b)
{
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
}
void main()
{
int a=1,b=2,c=3;
foo(&a,&b);
foo(&b,&c);
foo(&c,&a);
printf("%d","%d","%d",a,b,c);
}
foo(*a,*b) 交换a和b的值,所以经过a,b,c的值经过
foo(&b,&c);
foo(&c,&a);
foo() 用于交换数值
foo(&a,&b); //2,1,3
foo(&b,&c); 、、2,3,1,
foo(&c,&a); 、、1,3,2
#include<iostream>
using namespace std;
class A{
A(char *s){
cout<<s<endl;
}
~A(){}
};
class B:virtual public A{
public:
B(char *s1,char *s2):A(s1){
cout<<s2<<endl;
}
};
class C:virtual public A{
public:
C(hcar *s1,char *s2):A(s1){
cout<<s2<<endl;
}
};
class D: public B,public C{
public:
D(hcar *s1,char *s2,char *s3,char *s4):B(s1,s2),C(s1,s3),A(s1){
cout<<s4<<endl;
}
};
int main(){
D *p =new D("class A","class B","class C","class D");
delete p;
return 0;
}
对象生成构造顺序问题,先构造继承过来的父类,然后同级顺序构造
加了virtual后,继承关系是这样的
A
/ \
B C
\ /
D
不加的
A A
| |
B C
\ /
D
虚继承解决继承二义性,虚继承中对基类的构造是该类型的实例对象初始化,但D类型的实例对象对A类初始化只与D有关,不会再执行一次B、C中的构造,即ABCD。
#include<iostream>
using namespace std;
class A{
void test()
{
printf("test A");
}
};
int main()
{
A* pA =NULL;
pA->test();
return 0;
}
对于C++的设计者为了提高运行时的效率,实现静态绑定,也就是在运行之前就确定成员函数,
C++ 编译器这么干,
1. 查找pA的类型,发现有一个非虚的成员函数叫test。编译器干的
2. 找到生成函数调用,直接调用A::test(pA).
到了运行的时候,发现test()函数中没有任何解引用pA指针的代码,真实情况下也不会引发segment fault。这里对成员函数的解析,和查找对应的代码都是在编译阶段完成的,而非运行时完成的,这就是所谓的静态绑定,也就叫早绑定。
public int bsearch(int [] data,int x,int y, int v){
int m;
while(x<=y){ //1
m=x+(y-x)/2; //2
if(data[m]==v) return m;
else if(data[m]>v) y= m-1; //4
else x=m+1; // 5
}
}
注意没有包含上限,就需要对1 4 5 进行处理,m=x+(y-x)/2 是防止xy都很大的情况下x+y越界。
char *pa[7]
指针数组,每个元素char 型指针
vector::erase() 从指定容器删除指定位置的元素或某段范围内的元素
iterator erase(iterator_Where);
iterator erase(iterator_First,iterator_Last);
if 删除指定位置是,返回值是一个迭代器,指向删除元素的下一个元素;
如果是删除某个范围内的元素是,返回值也表示是一个迭代器,指向最后一个删除元素的下一个元素。