32位操作系统有32根地址线,每根两种状态0/1,表示2的32次方个内存单元,每个内存单元占1个字节(OS只能对字节进行操作,位操作用位操作符),1G = 2^10M,1M = 2^10K,1K = 2^10B,2^32B = 4*2^10*2^10*2^10 = 4G
知识点 1:
class Base
{
public:
virtual ~Base(){cout<<"~Base"<<endl;}
};
class Derive:public Base
{
public:
~Derive(){cout<<"~Derive"<<endl;}
};
main
Base *r = new Derive;
delete r;
/*
先调用子类的析构函数,再调用父类的析构函数
运行结果:
~Derive
~Base
*/
知识点 2:
enum e{
e1,
e2,
e3=10,
e4,
e5 = 'a',
e6
}epr;
main
cout<<e4<<","<<e6<<endl;
/*
运行结果:
11,98
*/
知识点 3:
struct st_t
{
int status;
short* pdata;
char errstr[32];
};
main
st_t st[16];
char *p = (char*)(st[2].errstr+32);
printf("%d", (p-(char*)(st)));
/*
结构体st_t 占4+4+32 = 40个字节,p-(char*)(st)包含st[0]、st[1]、st[2]
运行结果:
120
*/
知识点 4:
class AA
{
public:
void xoo(){}
char a, b;
};
//sizeof(AA) = 2
class AA
{
public:
void xoo(){}
};
//sizeof(AA) = 1
class AA
{
public:
void xoo(){}
char a;
};
//sizeof(AA) = 1
//同struct
知识点 5:
char *p[]={"TENCENT","CAMPUS","RECRUITING"};
char** pp[]={p+2,p+1,p};
char ***ppp = pp;
cout<<**++ppp<<endl;//CAMPUS
cout<<*++*++ppp<<endl;//CAMPUS
知识点 6:
int a[2][3] = {0, 2, 4, 6, 8, 10};
cout<<**(a+1)<<endl;//6
cout<<*(a[1]+1)<<endl;//8
cout<<**(a+1)+2<<endl;//8
cout<<*a[0]<<", "<<**a<<endl;//0
//a[0]表示第一行,a[1]表示第二行
知识点 7 :
char* chs[3]/* = {"Z189Z11", "84Z0Z11", "5Z11Z11"}*/;
chs[0] = new char[10];
chs[1] = new char[10];
chs[2] = new char[10];
//不能将字符串直接赋值给字符指针,原因是:指针指向的是字符串的第一个字符
strcpy(chs[0], "Z189Z11");
strcpy(chs[1], "84Z0Z11");
strcpy(chs[2], "5Z11Z11");
char* ch = "Z11";
int i = 0, j = 0, k = 0, num = 0;
for (; i<3; i++)
{
j = 0;
k = 0;
while(chs[i][j] != '\0' && ch[k] != '\0')
{
while(chs[i][j] == ch[k] && ch[k] != '\0')
{
j++;
k++;
}
if (k == 3)
{
num++;
j--;//判断连续Z11,倒回去一个
}
k = 0;
j++;
}
}
cout<<num<<endl;
for (int m = 2; m>=0; m--)
{
cout<<chs[m]<<endl;
}
for (int m = 0; m<3; m++)
{
delete[] chs[m];
}
知识点 8 :
//int *b = new int[];//不完整的类型
//int (*d)[2] = new int[][2];
//int (*f)[2][3] = new int[][2][3];
int *a = new int[34];
int (*c)[2] = new int[34][2];//申请34个两元素的一维数组
int (*e)[2][3] = new int[34][2][3];//申请34个2*3的二维数组
//char str1[];
char str2[]="01234";
cout<<a<<", "<<a+1<<endl;//相差4个字节
cout<<c<<", "<<c+1<<endl;//相差4*2个字节
cout<<e<<", "<<e+1<<endl;//相差4*2*3个字节
cout<<typeid(a).name()<<endl;//输出类型名
cout<<typeid(c).name()<<endl;
cout<<typeid(e).name()<<endl;
delete[] a; delete[] c; delete[] e;
知识点 9 :
//sizeof 计算的则是分配的数组chh[3] 所占的内存空间的大小,不受里面存储的内容影响
//strlen 计算字符串的长度,以'\0'为字符串结束标记
char *str1="absde";
char str2[]="01234";
char str3[8]={'a','b'};//只有前两个有值,其余都是空的
char str33[3] = {'c', 'd', 'e'};
char str333[3] = {'c', 'd'};
char *str4 = new char;
int *test = new int[8];
cout<<"sizeof(str1) = "<<sizeof(str1)<<endl;//4,指针变量占4
cout<<"sizeof(*str1) = "<<sizeof(*str1)<<endl;//1,实际上是第一个字符a所占内存
cout<<"sizeof(str2) = "<<sizeof(str2)<<endl;//6,加上'/0'
cout<<"sizeof(str3) = "<<sizeof(str3)<<endl;//8
cout<<"sizeof(str33) = "<<sizeof(str33)<<endl;//3
cout<<"sizeof(str333) = "<<sizeof(str333)<<endl;//3
cout<<"sizeof(test) = "<<sizeof(test)<<endl;//4,指针变量占4
cout<<"sizeof(str4) = "<<sizeof(str4)<<endl;//4,指针变量占4
cout<<endl;
cout<<"strlen(str1) = "<<strlen(str1)<<endl;//5,字符串长度
cout<<"strlen(str2) = "<<strlen(str2)<<endl;//5
cout<<"strlen(str3) = "<<strlen(str3)<<endl;//2,只关心存储的数据内容,不关心空间的大小和类型
cout<<"strlen(str33) = "<<strlen(str33)<<endl;//14 ? ?
cout<<"strlen(str333) = "<<strlen(str333)<<endl;//2
// cout<<"strlen(test) = "<<strlen(test)<<endl;//test 非字符串
cout<<"strlen(str4) = "<<strlen(str4)<<endl;//16 ? ?
memset(str2, 0, 2);//把数组的前两个元素清0,'\0'和0效果一样,如果是字符0,则用'0'
for (int i = 0; i<sizeof(str2); i++)//6
{
cout<<str2[i]<<",";
}
cout<<endl;
cout<<"sizeof(str2) = "<<sizeof(str2)<<endl;//6
cout<<"strlen(str2) = "<<strlen(str2)<<endl;//数组的第一个元素如果为'\0',则strlen(str2)为0,因为strlen计算字符串的长度,以'\0'为结束符,编译器检测到'\0'后,直接结束了
delete str4;
delete test;
知识点 10 :
int a[5] = {1,2,3};//不完全初始化,其他元素自动为0
cout<<"a[3] = "<<a[3]<<", a[4] = "<<a[4]<<endl;
//倒置一个数组中元素
int b[7] = {1, 2, 3, 4, 5, 6, 7};
int i = 0, j = 6;
int t;
while (i < j)
{
t = b[i];
b[i] = b[j];
b[j] = t;
i++;
j--;
}
for (i = 0; i < 7; i++)
{
cout<<b[i]<<endl;
}
知识点 11 :
int ii = 5;
int* pp1 = new int[4];//动态分配4个int型内存
int* pp2 = new int(4);//动态分配4个字节内存
*pp1 = 666;
*(pp1+1) = 777;
*(pp1+2) = 888;
*(pp1+3) = 999;
for (int i = 0; i < 4; i++)
{
cout<<*(pp1 + i)<<endl;
}
*pp2 = 111;
// *(pp2 + 1) = 222;//中断
for (int i = 0; i < 4; i++)
{
cout<<*(pp2 + i)<<endl;//第一个是111,后三个为不知名数
}
int* pp3 = ⅈ
cout<<*(pp3 + 1)<<endl;//pp3 + 1这个地址中的值可以打印,但是不能赋值,因为没有获得控制权
delete pp1;
delete pp2;
知识点 12 :
void f(int** q)//改变了p的指向
{
int i = 5;
*q = &i;//使p指向i
}
int main()
{
cout<<"*****************静态内存不能跨函数使用************************"<<endl;
int* p;
f(&p);
cout<<*p<<endl;//error,但是运行成功,编译器的bug
//f函数终止后,i的内存释放,此时p是野指针
p = NULL;
system("pause");
return 0;
}
知识点 13 :
void fun(char ch, int a = 6, float ff = 8.9)
{
cout<<a<<", "<<ff<<endl;
}
main()
int a = 76;
float ff = 4.3;
char ch = 'r';
fun(ch);
fun(ch, a);
fun(ch, a, ff);
/*
6, 8.9
76, 8.9
76, 4.3
*/
知识点 14:
char* p = new char[100];
strcpy(p, "Hytera");
strcat(p+2, "Downloader");
cout<<p<<endl;//HyteraDownloader
delete[] p;
//p的指向并没有改变
知识点 15:
int n[5] = {1,2,3,4,5};
int *ptr1 = (int*)(&n+1);//&n指向整个数组,保存的是首地址
int *ptr2 = (int*)(n+1);
cout<<n<<", "<<&n<<endl;
cout<<*(n+1)<<", "<<*(ptr1-1)<<*(ptr2-1)<<endl;
知识点 16:
vector<int> a(3,0);//包含3个0
vector<int> b(5,0);
b = a;//完全覆盖
a = vector<int>();//清零
cout<<int(a.size())<<endl;//0
cout<<int(b.size())<<endl;//3
知识点 16:
class A//8
{
int k[3];
public:
virtual void aa(){};
};
class B
{
int j;
public:
virtual void bb(){};
};
class C
{//char i;//4 char i[4];//4 char i[5];//8 char i[8];//char i[9];//12
char i[9];//只要有虚函数(4个字节),char每次分配4个字节
public:
virtual void cc(){};//4
};
class D
{
char m[3];//取决于此,3
public:
void dd(){};
};
main
cout<<sizeof(A)<<endl;
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
cout<<sizeof(D)<<endl;
知识点 17:
class A1//1
{};
class A2
{};
class B:public A1//1
{};
class C:public virtual B//4
{};
class D:public virtual A1, virtual public A2//8
{};
class E:public C//4
{};
class F:public A1, public A2//1
{};
知识点 18:
class N
{
protected:
int m_data;
public:
N(int data = 0)
{
m_data = data;
}
int GetData()
{
return doGetData();
}
virtual int doGetData()
{
return m_data;
}
};
class S:public N
{
protected:
int m_data;
public:
S(int data = 1)
{
m_data = data;
}
int doGetData()
{
return m_data;
}
};
class F:public S
{
protected:
int m_data;
public:
F(int data = 2)
{
m_data = data;
}
};
main
F x(10);
cout<<x.GetData()<<endl;
cout<<x.F::GetData()<<endl;
cout<<x.N::GetData()<<endl;
cout<<x.S::GetData()<<endl;
cout<<x.doGetData()<<endl;
cout<<x.F::doGetData()<<endl;
cout<<x.N::doGetData()<<endl;
cout<<x.S::doGetData()<<endl;
//结果:
/*
1
1
1
1
1
1
0
1
*/
知识点 18:
//倒序带头节点单向链表
typedef struct Node
{
int data;
struct Node* pNext;
}NODE, *PNODE;
//递归
void revSeq1(PNODE p,PNODE pHead)//p = pHead->pNext;
{
if(p->pNext==NULL)
{
pHead->pNext=p;
return;//找到最后一个节点
}
revSeq1(p->pNext,pHead);
p->pNext->pNext = p;//反转节点
p->pNext = NULL;//第一个节点反转后其后继应该为NULL
}
//非递归
PNODE revSeq2(PNODE pHead)
{
PNODE current, p;
current = pHead->pNext;
if (current == NULL)
{
return NULL;
}
while(current->pNext != NULL)
{
p = current->pNext;
current->pNext = p->pNext;
p->pNext = pHead->pNext;
pHead->pNext = p;
}
return pHead;
}
//倒序单向链表
int main()
{
//创建链表
PNODE pHead, pTail;
pHead = new NODE;
pTail = pHead;
pTail->pNext = NULL;
for (int i = 0; i<5; i++)
{
PNODE pNew = new NODE;
if (pNew == NULL)
{
cout<<"动态内存分配失败!"<<endl;
exit(-1);
}
pNew->data = i;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
//遍历链表
PNODE q = pHead->pNext;
while (q != NULL)
{
cout<<q->data<<", ";
q = q->pNext;
}
cout<<endl;
//逆序链表
PNODE pHead_rev = revSeq(pHead);
PNODE q1 = pHead->pNext;
while (q1 != NULL)
{
cout<<q1->data<<", ";
q1 = q1->pNext;
}
cout<<endl;
//释放内存
PNODE p = pHead;
PNODE r = p->pNext;
while (r != NULL)
{
delete p;
p = r;
r = r->pNext;
}
system("pause");
return 0;
}
current 始终指向 1这个节点
知识点 19:
char* p = "abc";
*(p+1) = 'g';//"abc"分配在文字常量区,p在栈区分配使指向"abc",常量"abc"不能被改变
cout<<p<<endl;//当指针指向常量字符串时,它的内容是不可以被修改的,否则在运行时会报错
/*
char *s1 的s1,而指针是指向一块内存区域,它指向的内存区域的大小可以随时改变,而且当指针指向常量字符串时,它的内容是不可以被修改的,否则在运行时会报错。
char s2[]的s2 是数组对应着一块内存区域,其地址和容量在生命期里不会改变,只有数组的内容可以改变
*/
知识点 20:
//float 与零值比较
const float EPSINON = 0.00001;
float x = 0.5;
if ((x >= - EPSINON) && (x <= EPSINON)){}