-
a是int型变量a的地址
(char *)将int型指针(指向4个字节)转换成char型指针(指向一个字节)
char *p声明一个char型指针变回量,答接受转换的地址。
#include <stdio.h>
int main()
{
int i = 0x1122;
char * p = (char *)&i;
if (p[0] == 0x22 && p[1] == 0x11) {
printf("Little Endian\n");
}
else if (p[0] == 0x11 && p[1] == 0x22) {
printf("Big Endian\n");
}
}查看全部 -
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
const int arrLength = 20; // 数组长度
double* getStusGrade()
{
// 学生成绩数组
double gradeArr[arrLength] = {
60.5, 62.5, 67.5, 40, 50, 60, 70, 80, 90, 100,
90.5, 12, 13.5, 84, 65, 76, 87, 88, 99, 20.5
};
// 堆内存上分配160个字节的内存空间 20×8个字节
double* arrP = (double*)malloc(arrLength * sizeof(double));
// 将栈内存上的数组数据添加到堆内存空间中
for (int index = 0; index < arrLength; index++)
{
arrP[index] = gradeArr[index];
}
return arrP;
}
int main(int argc, char** argv)
{
double* ptr = getStusGrade();
// 输出学生成绩
for (int index = 0; index < arrLength; index++)
{
std::cout << "学生" << index + 1 << "的数学成绩是:" << ptr[index] << std::endl;
}
free(ptr);
ptr = nullptr;
return 0;
}
查看全部 -
类的成员默认是私有的查看全部
-
向函数中传递一个对象:
若是直接在函数的参数列表中传递对象,那么这个传递到函数内部的对象仅仅是副本,造成资源浪费。
所以,一般选择使用指针或者引用作为函数列表中的对象引用
使用指针作为函数列表的参数时,为了增加健壮性还需要对指针进行判空操作。
因此可以选择使用引用传递对象
而且,可以使用const修饰来增加对象的存在周期,且指向不可修改。
查看全部 -
将父类的析构函数声明为虚函数,作用是用父类的指针删除一个派生类对象时,派生类对象的析构函数会被调用。例如:
class Staff
{
public:
std::string name;
int age;
virtual ~Staff()
{
}
}
class Coder : public Staff
{
public:
std::string language;
virtual ~Coder()
{
}
};
int main(int argc,char **argv)
{
Staff * s = new Coder();
delete s;
return 0;
}此时如果析构函数不加 virtual,那么 delete 父类指针的时候,子类的析构就不会被调用,某些情况下会导致内存泄漏。
查看全部 -
计算机硬件有两种储存数据的方式:大端字节序(big endian)和小端字节序(little endian)。
我们现在有一个整数514:。用16进制表示是0x0202,然后我们吧这个整数拆分成两个字节,第一个字节为0000 0010,第二个字节为0000 0010。
现在大部分的机器,都采用了小端字节序。但是在IO方面,则大部分使用大端字节序。例如:你要使用网络发送一个int类型的变量,要先把int转换成大端字节序,然后通过网络发送。
大端字节序又被称之为网络细节序。
查看全部 -
test
查看全部 -
面向过程的结构化编程:把数据放入到动作当中。采用自顶向下的方法构建程序,包含顺序,选择和循环三种结构。按照程序执行的时序步骤来完成。


类由成员函数和成员变量组成,可以通过实例化,得出很多的对象。
查看全部 -
运算符重载
RMB.h
class RMB { public: RMB(int _yuan, int _jiao, int _fen); ~RMB(); private: int yuan = 0; int jiao = 0; int fen = 0; };
RMB.cpp
#include "RMB.h" RMB::RMB(int _yuan, int _jiao, int _fen) { yuan = _yuan; jiao = _jiao; fen = _fen; } RMB::~RMB() { }
为这个类写了些必要的部分之后,我们要完成一个功能,加法功能,1块9毛加2块3毛,用程序应该怎么写呢?我们可以添加一个 Add 函数,如下:
RMB.h
class RMB { public: RMB(int _yuan, int _jiao, int _fen); ~RMB(); RMB Add(const RMB & rmb); private: int yuan = 0; int jiao = 0; int fen = 0; };
RMB.cpp
#include "RMB.h" RMB::RMB(int _yuan, int _jiao, int _fen) { yuan = _yuan; jiao = _jiao; fen = _fen; } RMB::~RMB() { } RMB RMB::Add(const RMB & rmb) { RMB rmbRes(0, 0, 0); // 分 int f = rmb.fen + fen; int f_ = f / 10; rmbRes.fen = f % 10; // 角 int j = rmb.jiao + jiao + f_; int j_ = j / 10; rmbRes.jiao = j % 10; // 元 int y = rmb.yuan + yuan + j_; int y_ = y / 10; rmbRes.yuan = y % 10; return rmbRes; }
这样,我们就实现了一个 Add 函数,如果想要把两个人民币加起来,就可以这样用:
int main(int argc,char **argv) { RMB rmbA(1, 9, 0); RMB rmbB(2, 5, 0); RMB rmbC = rmbA.Add(rmbB); return 0; }
但是这样看上去好像有点别扭,事实上,在很多不支持运算符重载的语言里,我们都是这样干的。但是在 C++ 里,有一种更好的方式,可以把 + 号进行重载。
我们可以把这个 Add 函数修改成 + 号的重载:
RMB.h
class RMB { public: RMB(int _yuan, int _jiao, int _fen); ~RMB(); // RMB & Add(const RMB & rmb); RMB operator + (const RMB & rmb); private: int yuan = 0; int jiao = 0; int fen = 0; };
RMB.cpp
#include "RMB.h" RMB::RMB(int _yuan, int _jiao, int _fen) { yuan = _yuan; jiao = _jiao; fen = _fen; } RMB::~RMB() { } // RMB & RMB::Add(const RMB & rmb) RMB RMB::operator + (const RMB & rmb) { RMB rmbRes(0, 0, 0); // 分 int f = rmb.fen + fen; int f_ = f / 10; rmbRes.fen = f % 10; // 角 int j = rmb.jiao + jiao + f_; int j_ = j / 10; rmbRes.jiao = j % 10; // 元 int y = rmb.yuan + yuan + j_; int y_ = y / 10; rmbRes.yuan = y % 10; return rmbRes; }
在这样修改之后,使用的时候,我们就可以写出来更优雅的代码了。
int main(int argc,char **argv) { RMB rmbA(1, 9, 0); RMB rmbB(2, 5, 0); RMB rmbC = rmbA + rmbB; return 0; }
可以看到我们直接把两个对象用 + 号加了起来,这比之前使用函数看起来会好得多。
在 C++ 中,有很多符号都可以重载,也有一些不能被重载。
查看全部 -
const修饰成员函数时,成员函数无法修改任何成员变量
const成员函数不能调用非const成员函数
查看全部 -
#include <iosteam>
#include "Data.h"
void test1(Data data)
{
}
void test2(Data * data)
{
//若传入空指针,加判断
if (data == nullprt)
{
return;
}
}
void test3(Data & data)//传引用不用做空指针判断
{
//存在通过引用操作data对象的漏洞
}
void test3(const Data & data)//加上const 函数内部无法操作data对象,规避漏洞。
{
}
Data getData()
{
Data data;//新建一个对象 == 新开一片内存
return data;
}
int main()
{
Data data;//创建副本
test 1(data);//操作副本
test 2(&data);//指针操作
test2(nullprt);//传入空指针
test3(data);//直接传入对象,更便捷。
Data data = getData();//调用结束,getData 返回的data内存释放,将之拷贝至新的内存对象“=”左边的那个data。(无形之中,资源浪费)
const Data & data = getData();
test3(data);//调用test3() 若data为const 修饰变量,test 函数内部赋值也必须为const修饰。
test3(getData());//简写。
return 0;
}
查看全部 -
引用
声明方法:
int main()
{
int A = 200;
int & newA = A; //引用初始化
newA = 90;
printf("A:%d\n",A);//A被赋值为90,操作newA 相当于操作A。
return 0;
}
本质相同:
int * newA = &A;//指针newA指向变量A的地址;
int & newA = A;//引用变量newA为A的地址。
区别:
指针:A *pa = &a;
pa->data =20;
pa->func();
引用:A &ra = a;
ra.data = 20;
ra.func();
1、指针可以不初始化,或初始化为空,引用不行。
2、引用不允许二次指向。
3、非大量内存操作时(例如数组),建议使用引用。
查看全部 -
纯虚函数的写法
class ClassA
{
//定义
public:
virtual int doWork() = 0;//纯虚函数(父类不实现,由子类实现)
virtual int doWork();//虚函数
};
class ClassB
{
public:
int doWork()
{
printf("ClassB::doWork() is called");
}
};
调用方法:
int main()
{
ClassA *ca = new classB();
ca->doWork();//调用了ClassB的doWork方法;
return0;
}
注意点:
1、虚函数在实现时,若子类需调用析构函数,父类的析构函数在定义时需加上virtual 前缀,否则默认调用父类的析构,子类的析构无法被调用。
2、1中若构造函数中开辟了新的堆内存,有内存溢出的风险。
查看全部 -
malloc函数是C语言中用于动态内存分配的标准库函数.
在使用malloc函数之前,需要包含stdlib.h头文件,以获得该函数的声明
调用malloc函数时,需要指定要分配的内存大小,参数为size_t类型,表示要分配的字节数。例如 malloc(2*sizeof(int))
查看全部 -
0x0102转化成0x0110
0001 0010
小端字节序 little endian (低地址)0010 0001 (高地址) 大部分机器(电脑)
大端字节序 big endian (低地址)0001 0010 (高地址) IO方面(网络细节序)
查看全部
举报

