<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[audi2的专栏]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/audi2</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; audi2]]></copyright><item><title><![CDATA[__VA_ARGS__的使用]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/168430549</link><guid>https://blog.youkuaiyun.com/audi2/article/details/168430549</guid><author>audi2</author><pubDate>Mon, 19 Oct 2026 10:35:03 +0800</pubDate><description><![CDATA[【代码】__VA_ARGS__的使用。]]></description><category></category></item><item><title><![CDATA[你真的会printf吗?]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/155539227</link><guid>https://blog.youkuaiyun.com/audi2/article/details/155539227</guid><author>audi2</author><pubDate>Wed, 03 Dec 2025 20:06:37 +0800</pubDate><description><![CDATA[precision]精度: 不同数据类型,有自己的精度定义. 以整数为例, 精度就是至少显示几位数字, 很容易想到, 如果精度值大, 实参值凑不到那个精度, 就会前补0。[width]宽度: 这个数据片断占据屏幕的宽度(一个英文asc码的宽度就是1个单位的宽度)以%为引导标志的格式控制符, 指定了如何把一个数据打印到屏幕。printf的若干参数, 有人还傻傻分不清吗?[length]长度: 数据类型的认定和转换。]]></description><category></category></item><item><title><![CDATA[JS 序列化类]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/134867531</link><guid>https://blog.youkuaiyun.com/audi2/article/details/134867531</guid><author>audi2</author><pubDate>Thu, 07 Dec 2023 23:16:32 +0800</pubDate><description><![CDATA[【代码】JS 序列化类。]]></description><category></category></item><item><title><![CDATA[阿里云MQTT: 子设备上线流程]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/134636490</link><guid>https://blog.youkuaiyun.com/audi2/article/details/134636490</guid><author>audi2</author><pubDate>Mon, 27 Nov 2023 04:47:07 +0800</pubDate><description><![CDATA[还有一点补充一下，如果阿里平台手动操作加的父子拓扑，并且网关设备里存的子设备密钥有效，则网关里认为的子设备类型，与平台认为的子设备类型可能不一致，造成传输错误。有一个解决方案，就是网关下的子设备透传自己定义的数据，传到平台后，用平台的”消息解析“功能做物模型翻译。ProducyKey,就会触发注册，拓扑这一套流程，执行后，要记住最重要的一点，把子设备的${SubDeviceSecret}写到E2ROM存起来。父网关必须已具备上线能力。剩下的工作就由父网关设备内部的软件，自动让设备注册，建立拓扑，上线。]]></description><category></category></item><item><title><![CDATA[aliyun MQTT ：纯透传配置]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/134599095</link><guid>https://blog.youkuaiyun.com/audi2/article/details/134599095</guid><author>audi2</author><pubDate>Fri, 24 Nov 2023 15:20:03 +0800</pubDate><description><![CDATA[在阿里平台拷贝连接参数（客户ID，用户名，密码，域名等），配置自己的设备（或者模拟设备的MQTTX客户端）。请参考其它网上资料，具体过程略。]]></description><category></category></item><item><title><![CDATA[加密那点事]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/134176890</link><guid>https://blog.youkuaiyun.com/audi2/article/details/134176890</guid><author>audi2</author><pubDate>Thu, 02 Nov 2023 15:23:53 +0800</pubDate><description><![CDATA[{公钥，私钥}是全球唯一的一对数据。2）你查看【济南市CA证书】的签发机构是山东省CA，然后你下载【山东省CA证书】，拿里面的山东省CA公钥给【济南是CA证书】做签名解密验证，发现成功了。1） 【我的证书】的签发机构是济南市CA，你要下载【济南市CA证书】，里面有济南市CA公钥给你用。因为本质还是CA私钥加密，你无法否认CA的身份，你是信任CA说法的，所以你也承认了证书的真实性。3）恰好呢，【国家CA】原本就在你的电脑里，你一直用它相信它，你做了最后一次验证，用国家CA的公钥验证【山东省CA证书】的签名。]]></description><category></category></item><item><title><![CDATA[sequence point]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/124128559</link><guid>https://blog.youkuaiyun.com/audi2/article/details/124128559</guid><author>audi2</author><pubDate>Tue, 12 Apr 2022 17:12:18 +0800</pubDate><description><![CDATA[顺序点，C语言冰山位于海面下的角落。
副作用side effect，简单理解就是变量值被改变这个事实。i++这个表达式，副作用就是i被增加1。a = 10；这个表达式，副作用就是a被赋值成10。
一个复杂的表达式，其求值过程是有迹可循的。例如：i++ + ++i 这个表达式，根据运算符的结合性或优先级关系，可以被人为是如下等效形式：(i++) + (++i).现在的问题来了，它的求值结果是什么？答案是：未定义行为（undefined）。未定义的意思是：无法预测结果。对比另一个叫做为未指定行为（unspeci]]></description><category></category></item><item><title><![CDATA[alias template，升级的typedef]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/123483609</link><guid>https://blog.youkuaiyun.com/audi2/article/details/123483609</guid><author>audi2</author><pubDate>Mon, 14 Mar 2022 17:34:10 +0800</pubDate><description><![CDATA[定义类型别名时，推荐用using B = A ；这种方式。



typedef void (*ANOTHER_TYPE)(int,int);  //废弃的用法
using ANOTHER_TYPE = void (*)(int,int); //鼓励使用的用法

template &lt;typename T&gt;
using ANOTHER_TYPE = void (*)(T,T); //因为typedef“不支持”参数,应使用alias template
//可以理解它是模板化的typedef


.]]></description><category></category></item><item><title><![CDATA[学习笔记：std::quoted]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/123359133</link><guid>https://blog.youkuaiyun.com/audi2/article/details/123359133</guid><author>audi2</author><pubDate>Tue, 08 Mar 2022 17:42:48 +0800</pubDate><description><![CDATA[CVS格式数据解析例子，使用std::quoted这个东西。



#include &lt;iostream&gt;
#include &lt;iomanip&gt;
#include &lt;sstream&gt;

void construct_cvs_formated_stream( std::stringstream&amp; ss)
{
    std::string row1 = R"NOTPRINTFLAG("12", "Chaoyang Qu, Jianguomen Dajie")NOT.]]></description><category></category></item><item><title><![CDATA[GIT 学习指导（6）]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/122368804</link><guid>https://blog.youkuaiyun.com/audi2/article/details/122368804</guid><author>audi2</author><pubDate>Sun, 09 Jan 2022 00:52:40 +0800</pubDate><description><![CDATA[git成名的地方在于分布式版本管理。其中的关键技术是远程分支。开发者的本地作品，相对于另一个开发者就是一个远程分支（别人的远程分支也是自己的本地分支，都是相互相对的）。本地分支和远程分支并行演进。如下图所示：



“远程"这个词可以扩展一下，在git里，本机的另外一个仓库位置，也可以认为是远程仓库。下面我们用本机的三个盘C: E: F:分别存储分布式仓库（模拟三个远程开发者协同工作的简单过程）。
...]]></description><category></category></item><item><title><![CDATA[GIT 学习指导（5）]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/122298805</link><guid>https://blog.youkuaiyun.com/audi2/article/details/122298805</guid><author>audi2</author><pubDate>Tue, 04 Jan 2022 11:35:41 +0800</pubDate><description><![CDATA[上文展示了merge命令，发现commit对象构成了一个类似有向图的数据结构。原因是一个commit拥有了两个父节点。这种结构不好看，我们还是喜欢单相链表那样的。git提供了另一种合并分支的命令，就是rebase。

    假设我们来到如下状态，两个平行的开发分支master和slave都是基于V1开发。我们想合并这两个分支。



git checkout slave #让我们设定当前分支是slave
git rebase master  #把slave分支移植到master，或者说重...]]></description><category></category></item><item><title><![CDATA[GIT 学习指导（4）]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/122187656</link><guid>https://blog.youkuaiyun.com/audi2/article/details/122187656</guid><author>audi2</author><pubDate>Wed, 29 Dec 2021 10:37:59 +0800</pubDate><description><![CDATA[分支就是一个单向的链表（节点是commit对象）。如下图例子：
   e---f  &lt;- slave
  /     
a---b---c---d &lt;- master &lt;- HEAD



]]></description><category></category></item><item><title><![CDATA[GIT 学习指导（3）]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/122106327</link><guid>https://blog.youkuaiyun.com/audi2/article/details/122106327</guid><author>audi2</author><pubDate>Fri, 24 Dec 2021 15:36:20 +0800</pubDate><description><![CDATA[上次是喝大了，写乱了一个文件a.c。如果这次喝大了写乱了多个文件怎么办（还提交了）？虽然git restore命令支持类似*.c的模式匹配一大批文件，但是我都喝大了，都不知道哪些文件搞乱了，也不愿意花时间一个个的比对了（因此也无法写出“文件模式*.c”），干脆我们就回退到上一个版本吧。这里和数据库的rollback不同，数据库在commit后，显然不能rollback了；GIT就可以回退版本。GIT使用一种叫做reset的命令回退版本。reset的意思是重新设置，重新设置什么？是重新设置的是分支的链表头指针]]></description><category></category></item><item><title><![CDATA[GIT 学习指导（2）]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/122089489</link><guid>https://blog.youkuaiyun.com/audi2/article/details/122089489</guid><author>audi2</author><pubDate>Wed, 22 Dec 2021 17:36:48 +0800</pubDate><description><![CDATA[考虑如下场景，我喝大了，把a.c这个文件写的乌七八糟。第二天早上，酒醒了。如何恢复a.c到“好”的版本？ 可以使用git restore命令。

这里有两个概念，一个是“从哪里取数据”，一个是“放到哪里”。
1. 从stage区取数据，放回到working区。
  例如：git add a.c  a.c文件照个快照(KEY=c5...)放到stage区
       date &gt;&gt; a.c 修改a.c文件（working区文件被修改）
       ...]]></description><category></category></item><item><title><![CDATA[GIT 学习指导（1）]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/122077760</link><guid>https://blog.youkuaiyun.com/audi2/article/details/122077760</guid><author>audi2</author><pubDate>Wed, 22 Dec 2021 11:09:47 +0800</pubDate><description><![CDATA[GIT是一种版本控制系统（Version Control System ）。我们在用原始方式保留历史版本时，会想到建立文件的拷贝。

GIT采用更巧妙的方式，把一个项目的所有文件保存到叫做Repository的文件数据库里。最终效果与人工拷贝一份文件夹备份是一样的，一个“版本”是项目某一时刻的全量快照。相对应的，某些其它竞争的VCS产品，可能采取增量记录法。既然GIT采取全量快照方式，代码文件每提交一次就咔嚓一份全量备份，对存储工作量岂不是海量的要求吗？GIT采取了精妙的数据结构，全量快照也不会浪费硬盘。.]]></description><category></category></item><item><title><![CDATA[BOOST.JSON库学习笔记（三）]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/118365538</link><guid>https://blog.youkuaiyun.com/audi2/article/details/118365538</guid><author>audi2</author><pubDate>Wed, 30 Jun 2021 17:40:23 +0800</pubDate><description><![CDATA[#include &lt;iostream&gt;

#include &lt;boost/json.hpp&gt;
using namespace boost::json;

int main(int argc, const char * argv[]) {


    array arr( { "Hello", 42, true });
    string str = "World";
    value var = false;

    object subobj{ {"subkey1",3.1.]]></description><category></category></item><item><title><![CDATA[BOOST.JSON库的学习笔记（二）]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/118362814</link><guid>https://blog.youkuaiyun.com/audi2/article/details/118362814</guid><author>audi2</author><pubDate>Wed, 30 Jun 2021 15:58:45 +0800</pubDate><description><![CDATA[#include &lt;boost/json.hpp&gt;
using namespace boost::json;

int main(int argc, const char * argv[]) {

    unsigned char buff[512];
    storage_ptr sp = make_shared_resource&lt;static_resource&gt;(buff);

    array arr( { "Hello", 42, true }, sp);
    s.]]></description><category></category></item><item><title><![CDATA[BOOST.JSON库的学习笔记（一）]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/118337911</link><guid>https://blog.youkuaiyun.com/audi2/article/details/118337911</guid><author>audi2</author><pubDate>Tue, 29 Jun 2021 16:48:16 +0800</pubDate><description><![CDATA[#include &lt;boost/json.hpp&gt;
using namespace boost::json;

int main(int argc, const char * argv[]) {

    value jv = 3.12;

    std::cout &lt;&lt; to_string( jv.kind());

    if (auto p = jv.if_double()) {  
        double d = *p;
        std::cout &lt.]]></description><category></category></item><item><title><![CDATA[C++17 pmr]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/118252089</link><guid>https://blog.youkuaiyun.com/audi2/article/details/118252089</guid><author>audi2</author><pubDate>Mon, 28 Jun 2021 15:26:05 +0800</pubDate><description><![CDATA[#include &lt;iostream&gt;
#include &lt;cstdlib&gt;
#include &lt;iostream&gt;
#include &lt;memory_resource&gt;
#include &lt;vector&gt;

int main() {
    char buffer[32] = {};
    std::fill_n(std::begin(buffer), std::size(buffer)-1, '_');
    std::cout &lt;.]]></description><category></category></item><item><title><![CDATA[asio::streambuf的使用]]></title><link>https://blog.youkuaiyun.com/audi2/article/details/117435729</link><guid>https://blog.youkuaiyun.com/audi2/article/details/117435729</guid><author>audi2</author><pubDate>Tue, 01 Jun 2021 11:39:18 +0800</pubDate><description><![CDATA[这个神器设计的非常巧妙，它有两个流缓冲区。一个input序列，一个output序列。比较难理解的是，在streambuf内部看来，它需要读取output序列，写入input序列，这一点不符合直觉。
]]></description><category></category></item></channel></rss>