2.11
DIY 物联网
VS2017基本操作
动态库创建、使用及其通用性
1)._declspec(dllexport)1用于Windows中的动态库
2) .def文件
环境配置
1). MKL 配置
2). wxWidges配置
小结:(VS配环境中)
①加.h文件:点编辑,写头文件路径
②加.lib文件:所有lib的路径
叁。加附加依赖项文件:
四。加宏定义
当因为少宏定义而报错时,往往如下:(API不安全)
在预处理器中添加
五。加那边的程序员自己写的额外的文件
则先找到那个外部符号所在文件,如图用VScode找
然后把它加到源文件下
得到,即可
六。加dll
比如出现这种dll找不到错误时
则先找到那个dll文件
然后把它复制到和.exe文件一个目录下,即可
#include
#include
#include
int main() {
const char* str1 = "helloworld"; //多字节版
const wchar_t* str2= L"helloworld"; //Unicode版,加L
const TCHAR* str3 = TEXT("helloworld"); //自适应,必须加TEXT()
return 0;
}
QoS=0,协议对此等级应用信息不要求回应确认,也没有重发机制,这类信息可能会发生消息丢失或重复,取决于TCP/IP提供的尽最大努力交互的数据包服务。
最少一次(At least once delivery):QoS=1,确保信息到达,但消息重复可能发生,发送者如果在指定时间内没有收到PUBACK控制报文,应用信息会被重新发送。
仅仅一次(Exactlyonce delivery):QoS=2,最高级别的服务质量,消息丢失和重复都是不可接受的。
低配置且资源受限,或者对网络流量有要求的设备,不适合直接构造JSON数据与物联网平台通信,可以怎样和物联网平台通信?
答案:MQTT客户端域名直接连接
错误原因:
我们看错误的问题为:无法打开某文件进行写入,原因在于,写MFC程序时,关闭了MFC窗口,但并没有关闭进程,MFC进程还在后台运行,导致无法再次编译运行。
#include
using namespace std;
class Circle
{
double PI = 3.1415;
//成员变量(属性)
double c_r;
double c_s;
//成员函数
public:
void set_r(double r)
{
c_r = r;
}
double set_s()
{
c_s = c_r * c_r*PI;
return c_s;
}
};
int main()
{
Circle c1;
double r ;
cout << "please input radio:";
cin >> r;
c1.set_r(r);
cout << "this is the area:" <<c1.set_s() << endl;
return 0;
}
using namespace namespaceB;
using namespaceB:namespaceC:Teacher;
Teacher t1;
register :放到寄存器
“CPU- 寄存器- 内存”,皇帝身边的小太监,是寄存器变量,他可以提高数据的存取速度,可以快速的存储以提高处理效率。
bool:
占用一个字节
其值不是1就是0;
若给他赋非0的数(eg:10,-10),其值就变成1
ADD:
①const是在编译器编译的的环节分配的地址(存储空间)。
下面三个语句,当扫描到后两个时,会分配地址
const int a=10;
printf("%d",&a);
p=(int *)&a
看作:对已定义变量(即一段连续的内存空间)的别名
本质:常量指针;
Type &name=var;《=》Type* const name=&var;
表现:\
①一个引用占4个字节内存(像一个指针)
而
②引用作为普通参数时必需初始化(像一个常量),不过作为函数参数时不必初始化
1)引用作为函数返回值
eg:
返回a的引用,就是把a的(本身)副本返回。
: 如果用一个变量去接,则返回a的值。
:如果用一个引用去接,则会返回a所标志的内存空间
对于局部变量。调 用完毕后,里面的内存被清除掉,所以会出现一个乱码
则 a2: 10, a3: 乱码
2)函数返回是个引用,并且作左值
经过g2()=100,相当于a=100.则变量a的值也变为100
: SPI:高速同步串行口。3~4线接口,收发独立、可同步进行
: UART:通用异步串行口。按照标准波特率完成双向通讯,速度慢
: I2C:一种串行传输方式,三线制,网上可找到其通信协议和用法的
#include
#include
int main()
{
initgraph(640, 480);
setfillcolor(BLUE);
for (int y = 0; y <= 480; y += 10)
{
fillcircle(100, y, 25);
Sleep(100);
cleardevice();
}
getchar();
closegraph();
return 0;
}
#include
#include
int main()
{
initgraph(640, 480);
for (int y = 0; y <= 480; y += 10)
{
setcolor(GREEN);
setfillcolor(BLUE);
fillcircle(100, y, 25);
Sleep(100);
/**
* 下面的意思是将绘制出来的圆在显示100毫秒后,将其用背景色覆盖掉
* 这样就达到了清除了操作
* 为什么不用cleardevice(),因为会将整个屏幕清空,而我们还想保留其他的画面呢
*/
setcolor(BLACK); //不仅填充色要求是黑色,而且边框色要得改变,默认白色
setfillcolor(BLACK);
fillcircle(100, y, 25);
}
getchar();
closegraph();
return 0;
}
LRESULT//表示会返回多种long型值
CALLBACK//只是为了识别这是一个回调函数的空宏
HWND//窗口句柄,整型值
UINT//unsigned int,WM_NOTIFY
WPARAM//typedef UINT WPARAM;control identifier
LPARAM//typedef LONG LPARAM;notification messages
消息响应机制
1、消息的组成:一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)。当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。例如当菜单转中之后会有WM_COMMAND消息发送,WPARAM的高字中(HIWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。当然用户也可以定义自己的消息名称,也可以利用自定义消息来发送通知和传送数据。
2、谁将收到消息:一个消息必须由一个窗口接收。在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。例如你希望对菜单选择进行处理那么你可以定义对WM_COMMAND进行处理的代码,如果希望在窗口中进行图形输出就必须对WM_PAINT进行处理。
3、未处理的消息到那里去了:M$为窗口编写了默认的窗口过程,这个窗口过程将负责处理那些你不处理消息。正因为有了这个默认窗口过程我们才可以利用Windows的窗口进行开发而不必过多关注窗口各种消息的处理。例如窗口在被拖动时会有很多消息发送,而我们都可以不予理睬让系统自己去处理。
4、窗口句柄:说到消息就不能不说窗口句柄,系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。例如有两个窗口共用一个窗口过程代码,你在窗口一上按下鼠标时消息就会通过窗口一的句柄被发送到窗口一而不是窗口二。
std::cerr
cerr和cout很像。对应标准错误流,用于显示错误消息。默认情况下被关联到标准输出流,但它不被缓冲,也就说错误消息可以直接发送到显示器,而无需等到缓冲区或者新的换行符时,才被显示。一般情况下不被重定向。
#include “Sales_items.h”
: 书籍销售
: 头文件需要额外加入
: Sales_item.h代码解析
const int和int const 是等价的
声明指向常量的指针也就是底层const; 声明常量指针就是顶层const
const int *const *const *pppi = &ppi;
//底层const,因为int前面const限定符,而最后一个*后面没有const限定符。
: 1 执行对象拷贝时有限制,常量的底层const不能赋值给非常量的底层const。
int num_c = 3;
const int *p_c = &num_c; //p_c为底层const的指针
//int *p_d = p_c; //错误,不能将底层const指针赋值给非底层const指针
const int *p_d = p_c; //正确,可以将底层const指针复制给底层const指针
const int a = 1;
//int * pi = &a; //错误,&a是底层const,不能赋值给非底层const
const int * pi = &a; //正确,&a是底层const,可以赋值给底层const
const int *const *const ppi = &pi //即是底层const,也是顶层const
const int *const *const *pppi = &ppi; //底层const
: 2 使用命名的强制类型转换函数const_cast时,需要能够分辨底层const和顶层const,因为const_cast只能改变运算对象的底层const。
理解复杂声明可用的“右左法则”:
从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。
举例:
int (func)(int p);
首 先找到变量名func,外面有一对圆括号,而且左边是一个号,这说明func是一个指针;然后跳出这个圆括号,先看右边,又遇到圆括号,这说明 (func)是一个函数,所以func是一个指向这类函数的指针,即函数指针,这类函数具有int类型的形参,返回值类型是int。
int (func[5])(int );
func 右边是一个[]运算符,说明func是具有5个元素的数组;func的左边有一个,说明func的元素是指针(注意这里的不是修饰func,而是修饰 func[5]的,原因是[]运算符优先级比高,func先跟[]结合)。跳出这个括号,看右边,又遇到圆括号,说明func数组的元素是函数类型的指 针,它指向的函数具有int*类型的形参,返回值类型为int。
也可以记住2个模式:
type ()(…)函数指针
type ()[]数组指针
2.陷阱
陷阱一:
记住,typedef是定义了一种类型的新别名,不同于宏,它不是简单的字符串替换。比如:
先定义:
typedef char* PSTR;
然后:
int mystrcmp(const PSTR, const PSTR);
const PSTR实际上相当于const char吗?不是的,它实际上相当于char const。
原因在于const给予了整个指针本身以常量性,也就是形成了常量指针char* const。
陷阱二:
typedef在语法上是一个存储类的关键字(如auto、extern、mutable、static、register等一样),故不能与他们同时出现
declaration specification(“声明规范”) ↩︎