//题目一:转义字符
/*
#include<iostream>
using namespace std;
int main()
{
// (ASCII的范围从0-127(十进制))
// \ddd 3位八进制
// \xhh 2位十六进制
int i;
// \ddd这种形式是\d,\dd,\ddd这三种形式都结束,\dddd就不接受了,最大三位,最大值的八进制为\177
// char *s = "8\n3\05\0\b"; //\05转换成八进制5
// char *s = "8\n3\050\0\b"; //把\050转换成八进制50,即十进制40对应的字符
// char *s = "8\n3\0500\0\b"; //把\050转换成八进制50,紧接着后面的就是字符0啦...
// char *s = "8\n3\000500\0\b"; //把\000转换成八进制0,紧接着是字符5,字符0,...
char *s = "8\n3\152\0\be"; //把\152转换成八进制152,即十进制106对应的字符
// \x与\ddd不同,可以读000000dd位(中间的0忽略),只要dd小于7f
// \x表示的 在前面加零不算,\x000000000011也解析为11,但是最大到\x7f,(ASCII的范围从0-127)
// char *s = "abc\x000011"; //把\x000011转换成十六进制11,即十进制17对应的字符
// char *s = "abc\x01a"; //把\x01a转换成十六进制1a,即十进制26对应的字符
for(i = 0; *s != 'e';*s++,i++)
{
printf("%d\n",*s);
}
return 0;
}
*/
//题目二:类中同名函数的覆盖
/*
#include<iostream>
using namespace std;
class A
{
public:
virtual void foo()
{
printf("A::foo\n");
}
};
class B : public A
{
public:
virtual void foo(int i)
{
printf("B::foo(%d)\n",i);
}
};
int main()
{
//在基类和派生类中使用同一名字的成员函数,其行为与数据成员一样:
//在派生类作用域中派生类成员将屏蔽基类成员。即使函数原型不同,基类成员与会被屏蔽;
B b;
// b.foo(); // 基类A中的foo()被派生类B中的同名函数foo(int)屏蔽,不能通过B的对象(引用或指针)调用
A *Apt = &b;
Apt->foo(); //但可以通过基类的对象/引用/指针来调用...
return 0;
}
*/
//题目三:NULL指针可以取值??
/*
#include<iostream>
using namespace std;
class A
{
public:
A(int value):m_value(value) { }
void fun1()
{
printf("fun1()\n");
}
void fun2()
{
printf("%d\n",m_value);
}
virtual void fun3()
{
printf("fun3()\n");
}
private:
int m_value;
};
int main()
{
// A* Apt ; //未初始化的指针不能用来取值
A* Apt = NULL ;
Apt->fun1(); //编译器会给fun1传入一个this指针,该指针为NULL。由于在fun1中,this指针并没有用到,因此运行正常
// Apt->fun2(); //运行fun2时,需要this指针才能得到m_value的值。由于此时this指针为NULL,因此导致内存访问出错。
// Apt->fun3(); //C++调用虚函数的时候,要根据实例(即this指针指向的实例)中虚函数表指针在虚函数表中找到函数的地址。
//由于这一步需要访问实例的地址(即this指针),而此时this指针为空指针,因此导致内存访问出错。
return 0;
}
*/
/*
//题目四:类有多大?
#include<stdio.h>
class A
{
//class A是一个空类型,它的实例不包含任何信息,本来求sizeof应该是0。
//但当我们声明该类型的实例的时候,它必须在内存中占有一定的空间,否则无法使用这些实例。
//至于占用多少内存,由编译器决定。Visual Studio 2008中每个空类型的实例占用一个byte的空间。
};
class B
{
//lass B在class A的基础上添加了构造函数和析构函数。
//由于类中函数的调用(包括构造函数和析构函数)调用与类型的实例无关(调用它们只需要知道函数地址即可),在它的实例中不需要增加任何信息。
//所以sizeof(B)和sizeof(A)一样,在Visual Studio 2008中都是1。
B(){};
~B(){};
void fun(int x) { printf("hello\n"); }
};
class C
{
//class C在class B的基础上把析构函数标注为虚拟函数。
//C++的编译器一旦发现一个类型中有虚拟函数,就会为该类型生成虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针。
//在32为的机器上,一个指针占4个字节的空间,因此sizeof(C)是4。
C(){};
virtual ~C(){};
};
int main()
{
printf("%d %d %d\n",sizeof(A),sizeof(B),sizeof(C)); //打印 1 1 4
return 0;
}
*/
/*
//题目五:struct/class/union内存对齐原则
// struct/class以及union内存对齐四个原则:
//1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,
// 以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。
//2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部"最宽基本类型成员"的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
//3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的"最宽基本类型成员"的整数倍.不足的要补齐.(基本类型不包括struct,class)
//4://sizeof(union),以结构里面size最大元素为union的size,因为在某一时刻,union只有一个成员真正存储于该地址
#include<iostream>
using namespace std;
union a
{
int a_int1;
double a_double; //8字节
int a_int2;
char ch;
//由原则4,a的大小为8
};
struct b
{
a a1; //[0]...[7] ,
char y; //[8]
//由原则3,"最宽基本类型成员"为a中的double,从而b的大小为8的整数倍,所以b的大小为16
};
class c
{
int c_double; //[0]...[4]
b b1; //[7]...[23] 原则2:与b的内部的最大元素的整数倍开始存储
char ch; //[24]
//由原则3,"最宽基本类型成员"为b中,即b里面a的double,c的大小为8的整数倍,所以c的大小为32
};
struct usc
{
char ch; //[0]
b b2; //[7]...[23] 原则2:与b的内部的最大元素的整数倍开始存储
a a2; //[24]...[31]
c c2; //[32]...[63]
char ch1; //[64]
//"最宽基本类型成员"为a中的double 或者 即b里面a的double 或者 c里面的b里面的double
//由原则3,usc的大小为8的整数倍,所以usc的大小为72
};
void main()
{
cout<<"sizeof(a)= "<<sizeof(a)<<endl;
cout<<"sizeof(b)= "<<sizeof(b)<<endl;
cout<<"sizeof(c)= "<<sizeof(c)<<endl;
cout<<"sizeof(usc)= "<<sizeof(usc)<<endl;
}
*/