<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://philleer.github.io/blogs.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://philleer.github.io/blogs.github.io/" rel="alternate" type="text/html" /><updated>2025-03-12T09:59:12+00:00</updated><id>https://philleer.github.io/blogs.github.io/feed.xml</id><title type="html">Technology blog</title><subtitle>❤ Good luck! ❤</subtitle><entry><title type="html">Python-Torch-Torchvision版本对照记录</title><link href="https://philleer.github.io/blogs.github.io/2024/12/11/python_torch_torchvision%E7%89%88%E6%9C%AC%E5%AF%B9%E7%85%A7%E8%AE%B0%E5%BD%95.html" rel="alternate" type="text/html" title="Python-Torch-Torchvision版本对照记录" /><published>2024-12-11T00:00:00+00:00</published><updated>2024-12-11T00:00:00+00:00</updated><id>https://philleer.github.io/blogs.github.io/2024/12/11/python_torch_torchvision%E7%89%88%E6%9C%AC%E5%AF%B9%E7%85%A7%E8%AE%B0%E5%BD%95</id><content type="html" xml:base="https://philleer.github.io/blogs.github.io/2024/12/11/python_torch_torchvision%E7%89%88%E6%9C%AC%E5%AF%B9%E7%85%A7%E8%AE%B0%E5%BD%95.html"><![CDATA[<p><strong>本文目录</strong></p>

<ol id="markdown-toc">
  <li><a href="#一torchvision与torch版本对应以及对python版本的要求" id="markdown-toc-一torchvision与torch版本对应以及对python版本的要求">一、torchvision与torch版本对应以及对python版本的要求</a></li>
  <li><a href="#二torchaudio与torch版本对应以及对python版本的要求" id="markdown-toc-二torchaudio与torch版本对应以及对python版本的要求">二、torchaudio与torch版本对应以及对python版本的要求</a></li>
  <li><a href="#三torch与torchvision和torchaudio以及cuda版本的对应" id="markdown-toc-三torch与torchvision和torchaudio以及cuda版本的对应">三、torch与torchvision和torchaudio以及cuda版本的对应</a></li>
  <li><a href="#四参考资料" id="markdown-toc-四参考资料">四、参考资料</a></li>
</ol>

<h3 id="一torchvision与torch版本对应以及对python版本的要求">一、torchvision与torch版本对应以及对python版本的要求</h3>

<table>
  <thead>
    <tr>
      <th>torch</th>
      <th>torchvision</th>
      <th>python</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>main/nightly</td>
      <td>main/nightly</td>
      <td>&gt;=3.9,&lt;=3.12</td>
    </tr>
    <tr>
      <td>2.5</td>
      <td>0.20</td>
      <td>&gt;=3.9,&lt;=3.12</td>
    </tr>
    <tr>
      <td>2.4</td>
      <td>0.19</td>
      <td>&gt;=3.8,&lt;=3.12</td>
    </tr>
    <tr>
      <td>2.3</td>
      <td>0.18</td>
      <td>&gt;=3.8,&lt;=3.12</td>
    </tr>
    <tr>
      <td>2.2</td>
      <td>0.17</td>
      <td>&gt;=3.8,&lt;=3.11</td>
    </tr>
    <tr>
      <td>2.1</td>
      <td>0.16</td>
      <td>&gt;=3.8,&lt;=3.11</td>
    </tr>
    <tr>
      <td>2.0</td>
      <td>0.15</td>
      <td>&gt;=3.8,&lt;=3.11</td>
    </tr>
    <tr>
      <td>1.13</td>
      <td>0.14</td>
      <td>&gt;=3.7.2,&lt;=3.10</td>
    </tr>
    <tr>
      <td>1.12</td>
      <td>0.13</td>
      <td>&gt;=3.7,&lt;=3.10</td>
    </tr>
    <tr>
      <td>1.11</td>
      <td>0.12</td>
      <td>&gt;=3.7,&lt;=3.10</td>
    </tr>
    <tr>
      <td>1.10</td>
      <td>0.11</td>
      <td>&gt;=3.6,&lt;=3.9</td>
    </tr>
    <tr>
      <td>1.9</td>
      <td>0.10</td>
      <td>&gt;=3.6,&lt;=3.9</td>
    </tr>
    <tr>
      <td>1.8</td>
      <td>0.9</td>
      <td>&gt;=3.6,&lt;=3.9</td>
    </tr>
    <tr>
      <td>1.7</td>
      <td>0.8</td>
      <td>&gt;=3.6,&lt;=3.9</td>
    </tr>
    <tr>
      <td>1.6</td>
      <td>0.7</td>
      <td>&gt;=3.6,&lt;=3.8</td>
    </tr>
    <tr>
      <td>1.5</td>
      <td>0.6</td>
      <td>&gt;=3.5,&lt;=3.8</td>
    </tr>
    <tr>
      <td>1.4</td>
      <td>0.5</td>
      <td>==2.7,&gt;=3.5,&lt;=3.8</td>
    </tr>
    <tr>
      <td>1.3</td>
      <td>0.4.2 / 0.4.3</td>
      <td>==2.7,&gt;=3.5,&lt;=3.7</td>
    </tr>
    <tr>
      <td>1.2</td>
      <td>0.4.1</td>
      <td>==2.7,&gt;=3.5,&lt;=3.7</td>
    </tr>
    <tr>
      <td>1.1</td>
      <td>0.3</td>
      <td>==2.7,&gt;=3.5,&lt;=3.7</td>
    </tr>
    <tr>
      <td>&lt;=1.0</td>
      <td>0.2</td>
      <td>==2.7,&gt;=3.5,&lt;=3.7</td>
    </tr>
  </tbody>
</table>

<h3 id="二torchaudio与torch版本对应以及对python版本的要求">二、torchaudio与torch版本对应以及对python版本的要求</h3>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20241211-torchversion-3.png#pic_center =640x932" alt="image" /></p>

<h3 id="三torch与torchvision和torchaudio以及cuda版本的对应">三、torch与torchvision和torchaudio以及cuda版本的对应</h3>

<table>
  <thead>
    <tr>
      <th>torch</th>
      <th>torchvision</th>
      <th>torchaudio</th>
      <th>cuda</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>2.5.0</td>
      <td>0.20.0</td>
      <td>2.5.0</td>
      <td>11.8/12.1/12.4</td>
    </tr>
    <tr>
      <td>2.4.1</td>
      <td>0.19.1</td>
      <td>2.4.1</td>
      <td>11.8/12.1/12.4</td>
    </tr>
    <tr>
      <td>2.4.0</td>
      <td>0.19.0</td>
      <td>2.4.0</td>
      <td>11.8/12.1/12.4</td>
    </tr>
    <tr>
      <td>2.3.1</td>
      <td>0.18.1</td>
      <td>2.3.1</td>
      <td>11.8/12.1</td>
    </tr>
    <tr>
      <td>2.3.0</td>
      <td>0.18.0</td>
      <td>2.3.0</td>
      <td>11.8/12.1</td>
    </tr>
    <tr>
      <td>2.2.2</td>
      <td>0.17.2</td>
      <td>2.2.2</td>
      <td>11.8/12.1</td>
    </tr>
    <tr>
      <td>2.2.1</td>
      <td>0.17.1</td>
      <td>2.2.1</td>
      <td>11.8/12.1</td>
    </tr>
    <tr>
      <td>2.2.0</td>
      <td>0.17.0</td>
      <td>2.2.0</td>
      <td>11.8/12.1</td>
    </tr>
    <tr>
      <td>2.1.2</td>
      <td>0.16.2</td>
      <td>2.1.2</td>
      <td>11.8/12.1</td>
    </tr>
    <tr>
      <td>2.1.1</td>
      <td>0.16.1</td>
      <td>2.1.1</td>
      <td>11.8/12.1</td>
    </tr>
    <tr>
      <td>2.1.0</td>
      <td>0.16.0</td>
      <td>2.1.0</td>
      <td>11.8/12.1</td>
    </tr>
    <tr>
      <td>2.0.1</td>
      <td>0.15.2</td>
      <td>2.0.2</td>
      <td>11.7/11.8</td>
    </tr>
    <tr>
      <td>2.0.0</td>
      <td>0.15.0</td>
      <td>2.0.0</td>
      <td>11.7/11.8</td>
    </tr>
    <tr>
      <td>1.13.1</td>
      <td>0.14.1</td>
      <td>0.13.1</td>
      <td>11.6/11.7</td>
    </tr>
  </tbody>
</table>

<h3 id="四参考资料">四、参考资料</h3>

<p>[1] <a href="https://github.com/pytorch/vision#installation">vision官方网站https://github.com/pytorch/vision#installation</a></p>

<p>[2] <a href="https://pytorch.org/audio/main/installation.html#compatibility-matrix">audio兼容版本https://pytorch.org/audio/main/installation.html#compatibility-matrix</a></p>

<p>[3] <a href="https://pytorch.org/get-started/previous-versions/">conda安装时不同版本的指令指南https://pytorch.org/get-started/previous-versions/</a></p>

<p>（全文完）</p>

<hr />

<blockquote>
  <p><strong>本文作者</strong>  ：phillee
<strong>发表日期</strong>  ：2024年12月11日
<strong>版权声明</strong>  ：自由转载-非商用-非衍生-保持署名（<a href="https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">创意共享3.0许可协议</a>/<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">CC BY-NC-SA 3.0</a>）。转载请注明出处！
限于本人水平，如果文章和代码有表述不当之处，还请不吝赐教。</p>
</blockquote>]]></content><author><name></name></author><summary type="html"><![CDATA[本文目录]]></summary></entry><entry><title type="html">下载并编译OpenCV脚本记录（支持图片和视频处理）</title><link href="https://philleer.github.io/blogs.github.io/2024/12/03/%E4%B8%8B%E8%BD%BD%E5%B9%B6%E7%BC%96%E8%AF%91OpenCV%E8%84%9A%E6%9C%AC%E8%AE%B0%E5%BD%95-%E6%94%AF%E6%8C%81%E5%9B%BE%E7%89%87%E5%92%8C%E8%A7%86%E9%A2%91%E5%A4%84%E7%90%86.html" rel="alternate" type="text/html" title="下载并编译OpenCV脚本记录（支持图片和视频处理）" /><published>2024-12-03T00:00:00+00:00</published><updated>2024-12-03T00:00:00+00:00</updated><id>https://philleer.github.io/blogs.github.io/2024/12/03/%E4%B8%8B%E8%BD%BD%E5%B9%B6%E7%BC%96%E8%AF%91OpenCV%E8%84%9A%E6%9C%AC%E8%AE%B0%E5%BD%95%EF%BC%88%E6%94%AF%E6%8C%81%E5%9B%BE%E7%89%87%E5%92%8C%E8%A7%86%E9%A2%91%E5%A4%84%E7%90%86%EF%BC%89</id><content type="html" xml:base="https://philleer.github.io/blogs.github.io/2024/12/03/%E4%B8%8B%E8%BD%BD%E5%B9%B6%E7%BC%96%E8%AF%91OpenCV%E8%84%9A%E6%9C%AC%E8%AE%B0%E5%BD%95-%E6%94%AF%E6%8C%81%E5%9B%BE%E7%89%87%E5%92%8C%E8%A7%86%E9%A2%91%E5%A4%84%E7%90%86.html"><![CDATA[<p>Ubuntu环境，源码编译OpenCV</p>

<p>基础环境包含c++编译和调试工具</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt update
<span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> build-essential cmake gdb
</code></pre></div></div>

<p>如果要支持opencv图片和视频处理至少还需要ffmpeg编解码相关的库（GStreamer库也可以）</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> libavcodec-dev libavformat-dev libavutil-dev libswscale-dev
</code></pre></div></div>

<p>脚本内容</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>

<span class="nv">RED</span><span class="o">=</span><span class="s1">'\033[0;31m'</span>
<span class="nv">YELLOW</span><span class="o">=</span><span class="s1">'\033[0;33m'</span>
<span class="nv">RES</span><span class="o">=</span><span class="s1">'\033[0m'</span>

<span class="nv">CURRENT_DIR</span><span class="o">=</span><span class="si">$(</span><span class="nb">pwd</span><span class="si">)</span>
<span class="nv">CURRENT_TIME</span><span class="o">=</span><span class="si">$(</span><span class="nb">date</span> +%Y%m%d%H%M%S<span class="si">)</span>

<span class="nv">POSTFIX</span><span class="o">=</span><span class="s2">"scripts"</span>
<span class="nv">LEN_POSTFIX</span><span class="o">=</span><span class="k">${#</span><span class="nv">POSTFIX</span><span class="k">}</span>
<span class="nv">DIR_POSTFIX</span><span class="o">=</span><span class="k">${</span><span class="nv">CURRENT_DIR</span>:0-7:<span class="k">${</span><span class="nv">LEN_POSTFIX</span><span class="k">}}</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"x</span><span class="k">${</span><span class="nv">DIR_POSTFIX</span><span class="k">}</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"x</span><span class="k">${</span><span class="nv">POSTFIX</span><span class="k">}</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
    </span><span class="nv">WORKSPACE</span><span class="o">=</span><span class="k">${</span><span class="nv">CURRENT_DIR</span><span class="k">}</span>/..
<span class="k">else
    </span><span class="nv">WORKSPACE</span><span class="o">=</span><span class="k">${</span><span class="nv">CURRENT_DIR</span><span class="k">}</span>
<span class="k">fi 

</span><span class="nv">OPENCV_DIR</span><span class="o">=</span><span class="k">${</span><span class="nv">WORKSPACE</span><span class="k">}</span>/opencv

<span class="k">if</span> <span class="o">[</span> <span class="o">!</span> <span class="nt">-d</span> <span class="k">${</span><span class="nv">OPENCV_DIR</span><span class="k">}</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">echo</span> <span class="s2">"Downloading opencv from GitHub"</span>
    git clone https://github.com/opencv/opencv.git
<span class="k">fi

</span><span class="nb">cd</span> <span class="k">${</span><span class="nv">OPENCV_DIR</span><span class="k">}</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"x</span><span class="nv">$2</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"x"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
    </span>git checkout 4.3.0 <span class="o">&amp;&amp;</span> git checkout <span class="nt">-b</span> v4.3.0
<span class="k">fi

</span><span class="nv">BUILD_DIR</span><span class="o">=</span><span class="k">${</span><span class="nv">OPENCV_DIR</span><span class="k">}</span>/build
<span class="nv">INSTALL_DIR</span><span class="o">=</span><span class="k">${</span><span class="nv">OPENCV_DIR</span><span class="k">}</span>/install

<span class="k">if</span> <span class="o">[</span> x<span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">==</span> x<span class="s2">"rebuild"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
    if</span> <span class="o">[</span> <span class="nt">-d</span> <span class="k">${</span><span class="nv">BUILD_DIR</span><span class="k">}</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
        </span><span class="nb">rm</span> <span class="nt">-rf</span> <span class="k">${</span><span class="nv">BUILD_DIR</span><span class="k">}</span> 
    <span class="k">fi
    if</span> <span class="o">[</span> <span class="nt">-d</span> <span class="k">${</span><span class="nv">INSTALL_DIR</span><span class="k">}</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
        </span><span class="nb">rm</span> <span class="nt">-rf</span> <span class="k">${</span><span class="nv">INSTALL_DIR</span><span class="k">}</span>
    <span class="k">fi
fi

if</span> <span class="o">[</span> <span class="o">!</span> <span class="nt">-d</span> <span class="k">${</span><span class="nv">BUILD_DIR</span><span class="k">}</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"</span><span class="k">${</span><span class="nv">BUILD_DIR</span><span class="k">}</span><span class="s2"> creating now..."</span>
    <span class="nb">mkdir</span> <span class="nt">-p</span> <span class="k">${</span><span class="nv">BUILD_DIR</span><span class="k">}</span>
<span class="k">else
    </span><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"</span><span class="k">${</span><span class="nv">YELLOW</span><span class="k">}${</span><span class="nv">BUILD_DIR</span><span class="k">}</span><span class="s2"> already exist</span><span class="k">${</span><span class="nv">RES</span><span class="k">}</span><span class="s2">"</span>
<span class="k">fi

</span><span class="nb">cd</span> <span class="k">${</span><span class="nv">BUILD_DIR</span><span class="k">}</span>
cmake <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Release <span class="se">\</span>
      <span class="nt">-DCMAKE_INSTALL_PREFIX</span><span class="o">=</span><span class="k">${</span><span class="nv">INSTALL_DIR</span><span class="k">}</span> <span class="se">\</span>
      <span class="nt">-DBUILD_SHARED_LIBS</span><span class="o">=</span>ON <span class="se">\</span>
      <span class="nt">-DWITH_FFMPEG</span><span class="o">=</span>ON <span class="se">\</span>
      <span class="nt">-DWITH_TBB</span><span class="o">=</span>OFF <span class="se">\</span>
      <span class="nt">-DBUILD_TESTS</span><span class="o">=</span>OFF <span class="se">\</span>
      <span class="nt">-DINSTALL_TESTS</span><span class="o">=</span>OFF <span class="se">\</span>
      ..
<span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> <span class="o">!=</span> <span class="s2">"0"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"</span><span class="k">${</span><span class="nv">RED</span><span class="k">}</span><span class="s2">[ERR]Failed to build the project</span><span class="k">${</span><span class="nv">RES</span><span class="k">}</span><span class="s2">"</span>
    <span class="nb">exit </span>1
<span class="k">fi

</span>make <span class="nt">-j4</span>
<span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> <span class="o">!=</span> <span class="s2">"0"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"</span><span class="k">${</span><span class="nv">RED</span><span class="k">}</span><span class="s2">[ERR]Failed to compile the project</span><span class="k">${</span><span class="nv">RES</span><span class="k">}</span><span class="s2">"</span>
    <span class="nb">exit </span>1
<span class="k">fi

</span>make <span class="nb">install</span> <span class="nt">-j4</span>
<span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> <span class="o">!=</span> <span class="s2">"0"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"</span><span class="k">${</span><span class="nv">RED</span><span class="k">}</span><span class="s2">[ERR]Failed to install the executables</span><span class="k">${</span><span class="nv">RES</span><span class="k">}</span><span class="s2">"</span>
    <span class="nb">exit </span>1
<span class="k">fi</span>
</code></pre></div></div>

<p>（全文完）</p>

<hr />

<blockquote>
  <p><strong>本文作者</strong>  ：phillee</p>

  <p><strong>发表日期</strong>  ：2024年12月03日</p>

  <p><strong>版权声明</strong>  ：自由转载-非商用-非衍生-保持署名（<a href="https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">创意共享3.0许可协议</a>/<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">CC BY-NC-SA 3.0</a>）。转载请注明出处！</p>

  <p>限于本人水平，如果文章和代码有表述不当之处，还请不吝赐教。</p>
</blockquote>]]></content><author><name></name></author><summary type="html"><![CDATA[Ubuntu环境，源码编译OpenCV]]></summary></entry><entry><title type="html">C语言时间结构体</title><link href="https://philleer.github.io/blogs.github.io/2023/06/29/C%E8%AF%AD%E8%A8%80%E6%97%B6%E9%97%B4%E7%BB%93%E6%9E%84%E4%BD%93.html" rel="alternate" type="text/html" title="C语言时间结构体" /><published>2023-06-29T00:00:00+00:00</published><updated>2023-06-29T00:00:00+00:00</updated><id>https://philleer.github.io/blogs.github.io/2023/06/29/C%E8%AF%AD%E8%A8%80%E6%97%B6%E9%97%B4%E7%BB%93%E6%9E%84%E4%BD%93</id><content type="html" xml:base="https://philleer.github.io/blogs.github.io/2023/06/29/C%E8%AF%AD%E8%A8%80%E6%97%B6%E9%97%B4%E7%BB%93%E6%9E%84%E4%BD%93.html"><![CDATA[<p><strong>本文目录</strong></p>

<ol id="markdown-toc">
  <li><a href="#一定义" id="markdown-toc-一定义">一、定义</a>    <ol>
      <li><a href="#1-初始定义-typedef重命名" id="markdown-toc-1-初始定义-typedef重命名">1. 初始定义-typedef重命名</a></li>
      <li><a href="#2-二阶定义-编译器相关" id="markdown-toc-2-二阶定义-编译器相关">2. 二阶定义-编译器相关</a></li>
      <li><a href="#3-终极定义-基础类型" id="markdown-toc-3-终极定义-基础类型">3. 终极定义-基础类型</a></li>
    </ol>
  </li>
  <li><a href="#二使用场景" id="markdown-toc-二使用场景">二、使用场景</a></li>
</ol>

<p>本文主要就C语言中常用类型<code class="language-plaintext highlighter-rouge">time_t</code>具体分析。</p>

<h3 id="一定义">一、定义</h3>

<h4 id="1-初始定义-typedef重命名">1. 初始定义-typedef重命名</h4>

<p>首先来看一下定义，原来是一种类型重命名。</p>

<pre><code class="language-C">/* File: /usr/include/time.h */
typedef __time_t time_t;
</code></pre>

<p>库文件中使用的其实是<code class="language-plaintext highlighter-rouge">__time_t</code>这个命名。</p>

<pre><code class="language-C">/* File: /usr/include/bits/time.h */
struct timeval
{
    __time_t tv_sec;        /* Seconds.  */
    __suseconds_t tv_usec;  /* Microseconds.  */
};
</code></pre>

<h4 id="2-二阶定义-编译器相关">2. 二阶定义-编译器相关</h4>

<p>接着看进一步的定义</p>

<pre><code class="language-C">/* File: /usr/include/bits/types.h */
__STD_TYPE __TIME_T_TYPE __time_t;  /* Seconds since the Epoch.  */
__STD_TYPE __USECONDS_T_TYPE __useconds_t; /* Count of microseconds.  */
__STD_TYPE __SUSECONDS_T_TYPE __suseconds_t; /* Signed count of microseconds.  */
</code></pre>

<p><code class="language-plaintext highlighter-rouge">__STD_TYPE</code>可以简单地理解为<code class="language-plaintext highlighter-rouge">typedef</code>。</p>

<p>首先<code class="language-plaintext highlighter-rouge">__WORDSIZE</code>是一个用于指示目标平台数据类型大小的宏。它的值取决于编译器以及编译时的目标架构。在 32位系统 中，<code class="language-plaintext highlighter-rouge">__WORDSIZE</code> 通常为 32。在 64位系统 中，<code class="language-plaintext highlighter-rouge">__WORDSIZE</code> 通常为 64。</p>

<p><code class="language-plaintext highlighter-rouge">__extension__</code>关键字的作用是告诉编译器允许使用非标准扩展。通常是为了提高兼容性或使用特定平台/编译器的特性。
所以结合起来看的话，如果我们用的是64位系统，那么这里的<code class="language-plaintext highlighter-rouge">__STD_TYPE</code>就是<code class="language-plaintext highlighter-rouge">typedef</code>。</p>

<pre><code class="language-C">#if __WORDSIZE == 32
# define __SQUAD_TYPE                __quad_t
# define __UQUAD_TYPE                __u_quad_t
# define __SWORD_TYPE                int
# define __UWORD_TYPE                unsigned int
# define __SLONG32_TYPE                long int
# define __ULONG32_TYPE                unsigned long int
# define __S64_TYPE                __quad_t
# define __U64_TYPE                __u_quad_t
/* We want __extension__ before typedef's that use nonstandard base types
   such as `long long' in C89 mode.  */
# define __STD_TYPE                __extension__ typedef
#elif __WORDSIZE == 64
# define __SQUAD_TYPE                long int
# define __UQUAD_TYPE                unsigned long int
# define __SWORD_TYPE                long int
# define __UWORD_TYPE                unsigned long int
# define __SLONG32_TYPE                int
# define __ULONG32_TYPE                unsigned int
# define __S64_TYPE                long int
# define __U64_TYPE                unsigned long int
/* No need to mark the typedef with __extension__.   */
# define __STD_TYPE                typedef
#else
# error
#endif
</code></pre>

<h4 id="3-终极定义-基础类型">3. 终极定义-基础类型</h4>

<p>继续上面的定义</p>

<p>可以看成是<code class="language-plaintext highlighter-rouge">typedef __TIME_T_TYPE __time_t;  /* Seconds since the Epoch.  */</code></p>

<p>那<code class="language-plaintext highlighter-rouge">__TIME_T_TYPE</code>又是如何定义的呢？</p>

<pre><code class="language-C">/* File: /usr/include/bits/typesizes.h */
#define __TIME_T_TYPE       __SLONGWORD_TYPE
#define __USECONDS_T_TYPE   __U32_TYPE
#define __SUSECONDS_T_TYPE  __SLONGWORD_TYPE
</code></pre>

<pre><code class="language-C">/* File: /usr/include/bits/types.h */
#define __S16_TYPE      short int
#define __U16_TYPE      unsigned short int
#define __S32_TYPE      int
#define __U32_TYPE      unsigned int
#define __SLONGWORD_TYPE    long int
#define __ULONGWORD_TYPE    unsigned long int
</code></pre>

<p>至此，可以确定，在64位系统下，<code class="language-plaintext highlighter-rouge">time_t</code>类型也即是<code class="language-plaintext highlighter-rouge">long int</code>类型</p>

<h3 id="二使用场景">二、使用场景</h3>

<p><code class="language-plaintext highlighter-rouge">time_t</code>类型的值如果想在<code class="language-plaintext highlighter-rouge">printf</code>中打印，使用格式符<code class="language-plaintext highlighter-rouge">PRId64</code>，该格式符定义包含在头文件<code class="language-plaintext highlighter-rouge">inttypes.h</code>中。</p>

<pre><code class="language-C">#include &lt;inttypes.h&gt;

struct timeval current_time;
gettimeofday(&amp;current_time, NULL);
fprintf(stdout, "current time stamp: %" PRId64 "\n", current_time.tv_sec);
</code></pre>

<p>（全文完）</p>

<hr />

<blockquote>
  <p><strong>本文作者</strong>  ：phillee</p>

  <p><strong>发表日期</strong>  ：2023年06月29日</p>

  <p><strong>版权声明</strong>  ：自由转载-非商用-非衍生-保持署名（<a href="https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">创意共享3.0许可协议</a>/<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">CC BY-NC-SA 3.0</a>）。转载请注明出处！</p>

  <p>限于本人水平，如果文章和代码有表述不当之处，还请不吝赐教。</p>
</blockquote>]]></content><author><name></name></author><summary type="html"><![CDATA[本文目录]]></summary></entry><entry><title type="html">Git内部状态管理和转换</title><link href="https://philleer.github.io/blogs.github.io/2021/12/27/Git%E5%86%85%E9%83%A8%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%B8%8E%E8%BD%AC%E6%8D%A2.html" rel="alternate" type="text/html" title="Git内部状态管理和转换" /><published>2021-12-27T00:00:00+00:00</published><updated>2021-12-27T00:00:00+00:00</updated><id>https://philleer.github.io/blogs.github.io/2021/12/27/Git%E5%86%85%E9%83%A8%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%B8%8E%E8%BD%AC%E6%8D%A2</id><content type="html" xml:base="https://philleer.github.io/blogs.github.io/2021/12/27/Git%E5%86%85%E9%83%A8%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%B8%8E%E8%BD%AC%E6%8D%A2.html"><![CDATA[<p>本文主要来介绍一下 Git 的内部状态管理系统。它利用基于节点和指针的数据结构来跟踪及管理编辑操作的时间线。</p>

<h3><strong><span style="background-color: #D6FEFE;">一、本地仓库各种状态之间</span></strong></h3>

<p>对本地项目而言，任一时刻，Git 处于三种状态中的一种：工作区状态(workspace)、暂存区状态(index/stage)和提交区状态(local repo)。
下面利用新建项目来演示一下不同状态及其转换。</p>

<h4><strong><span style="background-color: #D6FEFE;">1. 新建并初始化项目Initialize the project</span></strong></h4>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">mkdir </span>git_tree_test <span class="o">&amp;&amp;</span> <span class="nb">cd </span>git_tree_test

<span class="nv">$ </span>git init
提示：使用 <span class="s1">'master'</span> 作为初始分支的名称。这个默认分支名称可能会更改。要在新仓库中
提示：配置使用初始分支名，并消除这条警告，请执行：
提示：
提示：  git config <span class="nt">--global</span> init.defaultBranch &lt;名称&gt;
提示：
提示：除了 <span class="s1">'master'</span> 之外，通常选定的名字有 <span class="s1">'main'</span>、<span class="s1">'trunk'</span> 和  <span class="s1">'development'</span>。
提示：可以通过以下命令重命名刚创建的分支：
提示：
提示：  git branch <span class="nt">-m</span> &lt;name&gt;
已初始化空的 Git 仓库于 /Users/phillee/git_tree_test/.git/

<span class="nv">$ </span>git status
位于分支 master
尚无提交
无文件要提交（创建/拷贝文件并使用 <span class="s2">"git add"</span> 建立跟踪）
</code></pre></div></div>

<p>这时我们初始化了一个本地项目，默认处于 master 分支，尚无文件跟踪及提交。</p>

<h4><strong><span style="background-color: #D6FEFE;">2. 工作区The Working Directory</span></strong></h4>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">touch </span>git_add_hello.txt

<span class="nv">$ </span>git status
位于分支 master
尚无提交
未跟踪的文件:
  （使用 <span class="s2">"git add &lt;文件&gt;..."</span> 以包含要提交的内容）

        git_add_hello.txt

提交为空，但是存在尚未跟踪的文件（使用 <span class="s2">"git add"</span> 建立跟踪）
</code></pre></div></div>

<p>现在我们为项目新增了文件 git_add_hello.txt ，尚未提交，当前位于工作区（Working directory）。这里颜色效果没出来，这时 <span-red><b>git_add_hello.txt</b></span-red> 应该是<span-red>红色</span-red>的，表示还没有被跟踪。</p>

<h4><strong><span style="background-color: #D6FEFE;">3. 暂存区Staging Index</span></strong></h4>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git add git_add_hello.txt 

<span class="nv">$ </span>git status
位于分支 master
尚无提交
要提交的变更：
  （使用 <span class="s2">"git rm --cached &lt;文件&gt;..."</span> 以取消暂存）
        新文件：   git_add_hello.txt
</code></pre></div></div>

<p>所有变动的文件，Git 都记录在一个区域，叫做”暂存区”（Staging index）。我们通过 <code class="language-plaintext highlighter-rouge">git add</code> 指令将工作区中的内容保存到暂存区，这时已经实现了对文件的跟踪，但还没有请求提交。这时候的文件已经被跟踪了，<span-gre><b>git_add_hello.txt</b></span-gre> 应该是<span-gre>绿色</span-gre>的。</p>

<h4><strong><span style="background-color: #D6FEFE;">4. 提交区Local Repo</span></strong></h4>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git commit <span class="nt">-m</span> <span class="s2">"init commit"</span>
<span class="o">[</span>master（根提交） 88b5382] init commit
1 file changed, 0 insertions<span class="o">(</span>+<span class="o">)</span>, 0 deletions<span class="o">(</span>-<span class="o">)</span>
 create mode 100644 git_add_hello.txt

<span class="nv">$ </span>git status
位于分支 master
无文件要提交，干净的工作区
</code></pre></div></div>

<p>暂存区保留变动的文件信息，等到修改结束添加到本地仓库”提交历史”（Commit history）中，这就相当于当前项目的一个快照（snapshot）。
项目提交历史就是由不同时间的快照构成。Git 可以根据此提交信息将项目恢复到任意一个快照状态。</p>

<h4><strong><span style="background-color: #D6FEFE;">5. 反向状态转换Reverse state switching</span></strong></h4>

<p>前面叙述并展示了三种状态之间的前向转换，现在我们反过来看一下，如何将当前状态转换成其父状态。</p>

<p>首先新建一个测试文件并利用该文件进行不同状态之间转换的实验，按步骤2到步骤4的方式将新创建的文件添加到提交区中。</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">touch </span>gitadd_test_file
<span class="nv">$ </span><span class="nb">echo</span> <span class="s1">'Hello world!'</span> <span class="o">&gt;</span> gitadd_test_file

<span class="nv">$ </span>git status
位于分支 master
未跟踪的文件:
  （使用 <span class="s2">"git add &lt;文件&gt;..."</span> 以包含要提交的内容）
        gitadd_test_file

提交为空，但是存在尚未跟踪的文件（使用 <span class="s2">"git add"</span> 建立跟踪）

<span class="nv">$ </span>git add gitadd_test_file 
<span class="nv">$ </span>git commit <span class="nt">-m</span> <span class="s2">"add one file for test"</span>
<span class="o">[</span>master d97ee77] add one file <span class="k">for </span><span class="nb">test
 </span>1 file changed, 1 insertion<span class="o">(</span>+<span class="o">)</span>
 create mode 100644 gitadd_test_file

<span class="nv">$ </span>git log <span class="nt">--oneline</span>
d97ee77 <span class="o">(</span>HEAD -&gt; master<span class="o">)</span> add one file <span class="k">for </span><span class="nb">test
</span>88b5382 init commit
</code></pre></div></div>

<ul>
  <li>(1) 提交区状态转换成暂存区状态</li>
</ul>

<p>现在我们尝试将已经提交 <code class="language-plaintext highlighter-rouge">commit</code> 但尚未 <code class="language-plaintext highlighter-rouge">push</code> 到远端仓库的状态返回到暂存区状态。此时的<span-gre><b>gitadd_test_file</b></span-gre>为<span-gre>绿色</span-gre>。</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git reset <span class="nt">--soft</span> HEAD^
<span class="nv">$ </span>git status
位于分支 master
要提交的变更：
  （使用 <span class="s2">"git reset HEAD &lt;文件&gt;..."</span> 以取消暂存）
        新文件：   gitadd_test_file
</code></pre></div></div>

<p>如上结果所示，这时已经处于<code class="language-plaintext highlighter-rouge">git commit</code>命令之前的状态，达到此结果使用的是<code class="language-plaintext highlighter-rouge">git reset --soft</code>指令。
该操作会保留文件的改动及索引状态，撤销完成后将回到添加改动的状态。</p>

<p>此处由于提交历史比较简单，是单一分支一串到底，<code class="language-plaintext highlighter-rouge">HEAD^</code>和<code class="language-plaintext highlighter-rouge">HEAD~</code>都是指代上一次提交的提交区状态，也就是前一个代码快照。</p>

<p>注意<code class="language-plaintext highlighter-rouge">git reset --soft</code>与接下来要使用的<code class="language-plaintext highlighter-rouge">git reset --hard</code>之间的区别。此时的<span-gre><b>gitadd_test_file</b></span-gre>为<span-gre>绿色</span-gre>。</p>

<ul>
  <li>(2) 暂存区状态转换成工作区状态</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git reset HEAD gitadd_test_file 
<span class="nv">$ </span>git status
位于分支 master
未跟踪的文件:
  （使用 <span class="s2">"git add &lt;文件&gt;..."</span> 以包含要提交的内容）
        gitadd_test_file

提交为空，但是存在尚未跟踪的文件（使用 <span class="s2">"git add"</span> 建立跟踪）
</code></pre></div></div>

<p>通过<code class="language-plaintext highlighter-rouge">git reset HEAD</code>指令，我们得以将暂存区状态转换到工作区状态，也就是<code class="language-plaintext highlighter-rouge">git add</code>之前的状态。此时的<span-red><b>gitadd_test_file</b></span-red>为<span-red>红色</span-red>。</p>

<p><code class="language-plaintext highlighter-rouge">git reset</code>其实默认是执行<code class="language-plaintext highlighter-rouge">git reset --mixed</code>指令的操作，没有指定soft/mixed/hard参数时即按照<code class="language-plaintext highlighter-rouge">mixed</code>参数执行。</p>

<ul>
  <li>(3) 提交区状态转换成工作区状态</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git add gitadd_test_file 
<span class="nv">$ </span>git commit <span class="nt">-m</span> <span class="s2">"add test file for git add test"</span>
<span class="o">[</span>master d535a57] add <span class="nb">test </span>file <span class="k">for </span>git add <span class="nb">test
 </span>1 file changed, 1 insertion<span class="o">(</span>+<span class="o">)</span>
 create mode 100644 gitadd_test_file

<span class="nv">$ </span>git log <span class="nt">--oneline</span>
d535a57 <span class="o">(</span>HEAD -&gt; master<span class="o">)</span> add <span class="nb">test </span>file <span class="k">for </span>git add <span class="nb">test
</span>88b5382 init commit
<span class="nv">$ </span>git reset <span class="nt">--hard</span> HEAD^
HEAD 现在位于 88b5382 init commit
<span class="nv">$ </span>git status
位于分支 master
无文件要提交，干净的工作区
</code></pre></div></div>

<p>这里是将<code class="language-plaintext highlighter-rouge">gitadd_test_file</code>重新添加到暂存区，然后保存到提交历史。重新提交后SHA值会发生变化。然后从提交区状态直接返回到<code class="language-plaintext highlighter-rouge">git add</code>之前的工作区状态，使用的指令是<code class="language-plaintext highlighter-rouge">git reset --hard</code>，该指令强制将<code class="language-plaintext highlighter-rouge">HEAD</code>指针指向提交历史线中的前一个提交状态，会连同上次提交之后新建的文件一起全部撤销。如果没有新增文件只有改动，则改动会丢失，相对soft而言不够灵活<strong>该举动有一定风险，使用时要注意场合。</strong>当然即使这么操作了也并非就不能复原了，只是会多几步操作而已。</p>

<h3><strong><span style="background-color: #D6FEFE;">二、本地仓库与远程仓库各种状态之间</span></strong></h3>

<p>相比于第一部分的状态回滚，这部分内容属于广义上的状态切换了，相对比较容易理解掌握和应用。
假设本地仓库和远程仓库之间已经建立了连接(<code class="language-plaintext highlighter-rouge">git remote add origin https://github.com/username/reponame.git</code>)，有以下三种状态转换。</p>

<ul>
  <li>(1) 将远程仓库更新到与本地仓库状态一致</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin master
</code></pre></div></div>

<p>在本地仓库找到与 master 匹配的分支引用，用它更新远程仓库中的同名分支。 如果远程仓库不存在该分支，则会新创建分支并更新。master可以替换成其他分支名。还有一种更简便的方法，直接将当前所在分支的更新应用到远程仓库，使用HEAD指针：<code class="language-plaintext highlighter-rouge">git push origin HEAD</code>。</p>

<ul>
  <li>(2) 拉取远程仓库更新到本地仓库</li>
</ul>

<p>指令格式</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git fetch &lt;远程主机名&gt; &lt;分支名&gt;
</code></pre></div></div>

<p>常见的使用场景如取回 origin 主机的 master 分支</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git fetch origin master
</code></pre></div></div>

<p>该指令将远程仓库中与当前分支同名的关联分支内容更新到本地仓库。同时返回一个FETCH_HEAD指针，指向master在服务器上的最新状态，在本地可以通过它查看刚取回的更新信息。</p>

<p>注意与下一小节使用的命令<code class="language-plaintext highlighter-rouge">git pull</code>的区别，fetch指令只将远程仓库的内容拉到本地仓库，属于状态图中的Local repo阶段，并未应用到工作区workspace。</p>

<ul>
  <li>(3) 拉取远程仓库更新到本地工作区</li>
</ul>

<p>完整格式可表示如下，如果远程分支是与当前分支合并，则冒号后面的部分可以省略。</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git pull &lt;远程主机名&gt; &lt;远程分支名&gt;:&lt;本地分支名&gt;
</code></pre></div></div>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git pull origin master
</code></pre></div></div>

<p>将远程仓库中与当前分支同名的关联分支内容更新到本地并合并到当前工作区。其效果相当于<code class="language-plaintext highlighter-rouge">git fetch origin master &amp;&amp; git merge FETCH_HEAD</code>，在<code class="language-plaintext highlighter-rouge">git fetch</code>从远程仓库的master分支拉取最新内容后将拉取下来的最新内容合并到当前分支的工作区中。</p>

<p>（全文完）</p>

<hr />

<blockquote>
  <p>【原创】首发于博客园</p>
</blockquote>

<style>
	span-dol {
		color: #377E7F;
	}
    span-red {
        color: #CD3B52;
    }
    span-gre {
        color: #54A559;
    }
</style>

<blockquote>
  <p><strong>本文作者</strong>  ：phillee
<strong>发表日期</strong>  ：2021年3月30日
<strong>版权声明</strong>  ：自由转载-非商用-非衍生-保持署名（<a href="https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">创意共享3.0许可协议</a>/<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">CC BY-NC-SA 3.0</a>）。转载请注明出处！
限于本人水平，如果文章和代码有表述不当之处，还请不吝赐教。</p>
</blockquote>

<style>
.outter_box {
      text-align: center;
}
.button {
    background-color: #53A849; /* Green */
    border: none;
    border-radius: 6px;
    color: white;
    padding: 9px 24px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
}
.img_box{
      border: none;
      color: white;
      text-align: center;
      vertical-align: middle;
}
.demo{
  width: 208px;
  height: 260px;
  margin: 0 auto;
}
.demo img{
  -webkit-filter: drop-shadow(2px 2px 5px rgba(0,0,0,.5));
  filter: drop-shadow(2px 2px 5px rgba(0,0,0,.5));
}
</style>

<script language="javascript">
  function display(id){
    var traget=document.getElementById(id);
    if(traget.style.display=="none"){
      traget.style.display="";
    }else{
      traget.style.display="none";
    }
  }
</script>

<p style="text-align:center"><font size="4" color="gray">感谢您的支持</font></p>
<div class="outter_box">
      <div class="button">&#xA5;&nbsp;打赏</div>
</div>
<p></p>
<div class="img_box" id="oImg" style="">
    <div class="demo">
          <p style="text-align:center;"><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/wechat_receiver.jpg" /></p>
          <p style="text-align:center;"><font color="gray">微信支付</font></p>
    </div>
</div>]]></content><author><name></name></author><summary type="html"><![CDATA[本文主要来介绍一下 Git 的内部状态管理系统。它利用基于节点和指针的数据结构来跟踪及管理编辑操作的时间线。]]></summary></entry><entry><title type="html">Git commit开发规范学习与总结</title><link href="https://philleer.github.io/blogs.github.io/2021/12/24/Git-commit%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83%E6%80%BB%E7%BB%93.html" rel="alternate" type="text/html" title="Git commit开发规范学习与总结" /><published>2021-12-24T00:00:00+00:00</published><updated>2021-12-24T00:00:00+00:00</updated><id>https://philleer.github.io/blogs.github.io/2021/12/24/Git%20commit%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83%E6%80%BB%E7%BB%93</id><content type="html" xml:base="https://philleer.github.io/blogs.github.io/2021/12/24/Git-commit%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83%E6%80%BB%E7%BB%93.html"><![CDATA[<h3 id="0前言">0.前言</h3>

<p>好的提交信息有利于我们对项目的理解、开发和维护，值得花时间了解学习。</p>

<ul>
  <li>(1) 提高项目的整体规范性</li>
  <li>(2) 历史提交清晰明了，可读性好，方便快速浏览或查找</li>
  <li>(3) 便于跟踪工程历史及Code Reviewing</li>
  <li>(4) 便于直接从提交历史生成变更日志</li>
</ul>

<h3 id="1概述">1.概述</h3>

<p>被广泛认可并应用的应该是<a href="https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines">Angular Git Commit Guidelines</a>，其规范如下。</p>

<p>一条规范的提交信息包含标题、主体内容和注脚，三者分别用空行隔开。书写格式</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;<span class="nb">type</span><span class="o">&gt;(</span>&lt;scope&gt;<span class="o">)</span>: &lt;subject&gt;
&lt;BLANK LINE&gt;
&lt;body&gt;
&lt;BLANK LINE&gt;
&lt;footer&gt;
</code></pre></div></div>

<p><strong>通用规则</strong></p>

<ul>
  <li>提交信息中的每一行都不要超过100个字符。</li>
  <li>如果本次提交是使用<code class="language-plaintext highlighter-rouge">revert</code>命令回滚之前的某次提交，提交信息的标题前面应该再加上<code class="language-plaintext highlighter-rouge">revert: </code>字样。同时在主体内容中应注明<code class="language-plaintext highlighter-rouge">This reverts commmit &lt;hash&gt;.</code>，这里的hash指的是本次提交对应的历史提交的SHA值。</li>
</ul>

<h3 id="2标题">2.标题</h3>

<p>我们称第一行的<code class="language-plaintext highlighter-rouge">&lt;type&gt;(&lt;scope&gt;): &lt;subject&gt;</code>部分为提交信息标题。
一个标题占单独一行，一般要求50个字符以内，包含对更改简明扼要的描述。由更改类型、应用范围和提交主题构成，应用范围有时可省略。</p>

<h4 id="21-更改类型">2.1 更改类型</h4>

<p><code class="language-plaintext highlighter-rouge">&lt;type&gt;</code>部分指出当前提交所提供的改变属于哪种类型。</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">feat</code>: (feature) 添加新特性</li>
  <li><code class="language-plaintext highlighter-rouge">fix</code>: (bug fix) 修复漏洞</li>
  <li><code class="language-plaintext highlighter-rouge">docs</code>: (documentation) 仅修改文档，如增删改的提交</li>
  <li><code class="language-plaintext highlighter-rouge">style</code>: (formatting, missing semi colons etc) 仅修改排版格式，如缩进、空格/制表符/空行、逗号等不改变代码逻辑的内容的提交</li>
  <li><code class="language-plaintext highlighter-rouge">refactor</code>: 没有增加新特性或修复漏洞的代码重构</li>
  <li><code class="language-plaintext highlighter-rouge">test</code>: (add missing or correct existing tests) 增加新的或者改正当前测试用例</li>
  <li><code class="language-plaintext highlighter-rouge">perf</code>: (improve performance) 提升性能</li>
  <li><code class="language-plaintext highlighter-rouge">chore</code>: (maintain) 维护，改变构建流程、增加依赖库等</li>
</ul>

<h4 id="22-应用范围">2.2 应用范围</h4>

<ul>
  <li><code class="language-plaintext highlighter-rouge">&lt;scope&gt;</code>部分用于指出本次提交影响或涉及的范围，如<code class="language-plaintext highlighter-rouge">$location, $browser, $compile, $rootScope, ngHref, ngClick, ngView, etc</code>，可能会是数据层、控制层、视图层等。</li>
  <li>当没有合适的范围描述方法时可以省略，或者当提交涉及的范围不止一个时也可以用一个星号<code class="language-plaintext highlighter-rouge">*</code>替代。</li>
</ul>

<h4 id="23-提交主题">2.3 提交主题</h4>

<p><code class="language-plaintext highlighter-rouge">&lt;subject&gt;</code>部分是对提交更改的简要描述。Angular规范提出以下三个要求。</p>

<ul>
  <li>(1) 使用祈使句、一般现在时态 (eg:“change” not “changed” nor “changes”)</li>
  <li>(2) 首字母不要大写</li>
  <li>(3) 末尾不要加标点</li>
</ul>

<h3 id="3主体内容">3.主体内容</h3>

<p>内容部分用来详细描述本次提交做了哪些更改、为什么进行这些更改、会产生什么结果等的信息。基本原则罗列如下，可以根据实际情况适当调整。</p>

<ul>
  <li>(1) 和提交主题部分相同，使用祈使句、一般现在时</li>
  <li>(2) 为何进行这个变更，可能是修复漏洞、增加新特性或提升性能、稳定性等</li>
  <li>(3) 与改变之前相比结果会有何变化</li>
  <li>(4) 用于解决什么问题，如何解决，具体描述解决问题的步骤</li>
  <li>(6) 是否存在副作用或潜在风险</li>
</ul>

<h3 id="4注脚">4.注脚</h3>

<h4 id="41-突破性进展或不兼容变动">4.1 突破性进展或不兼容变动</h4>

<p>所有的突破性进展或不兼容变动都应该在注脚中明确标注出来，以<code class="language-plaintext highlighter-rouge">BREAKING CHANGE:</code>开头，后面跟一个空格或者两个空行。剩余的部分用来描述更改内容、理由和迁移说明(the description of the change, justification and migration notes)。</p>

<h4 id="42-参考问题">4.2 参考问题</h4>

<p>修复与某个问题(issue)相关的漏洞之后，应该把终结的问题在注脚信息中单独一行罗列出来，加上关键词<code class="language-plaintext highlighter-rouge">Closes</code>作为前缀。</p>

<p>例如终结一个相关问题<code class="language-plaintext highlighter-rouge">Closes #234</code>或同时终结多个相关问题<code class="language-plaintext highlighter-rouge">Closes #123, #245, #992</code>。注意问题要附加超链接。</p>

<h3 id="5参考示例">5.参考示例</h3>

<ul>
  <li>
    <p>示例1</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  style<span class="o">(</span><span class="nv">$location</span><span class="o">)</span>: add couple of missing semi colons
</code></pre></div>    </div>
  </li>
  <li>
    <p>示例2</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  feat<span class="o">(</span>directive<span class="o">)</span>: ng:disabled, ng:checked, ng:multiple, ng:readonly, ng:selected

  New directives <span class="k">for </span>proper binding these attributes <span class="k">in </span>older browsers <span class="o">(</span>IE<span class="o">)</span><span class="nb">.</span>
  Added coresponding description, live examples and e2e tests.

  Closes <span class="c">#351</span>
</code></pre></div>    </div>
  </li>
  <li>
    <p>示例3</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  feat<span class="o">(</span><span class="nv">$browser</span><span class="o">)</span>: onUrlChange event <span class="o">(</span>popstate/hashchange/polling<span class="o">)</span>

  Added new event to <span class="nv">$browser</span>:
  - forward popstate event <span class="k">if </span>available
  - forward hashchange event <span class="k">if </span>popstate not available
  - <span class="k">do </span>polling when neither popstate nor hashchange available

  Breaks <span class="nv">$browser</span>.onHashChange, which was removed <span class="o">(</span>use onUrlChange instead<span class="o">)</span>
</code></pre></div>    </div>
  </li>
  <li>
    <p>示例4</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  docs<span class="o">(</span>guide<span class="o">)</span>: updated fixed docs from Google Docs

  Couple of typos fixed:
  - indentation
  - batchLogbatchLog -&gt; batchLog
  - start periodic checking
  - missing brace
</code></pre></div>    </div>
  </li>
  <li>
    <p>示例5</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  feat<span class="o">(</span><span class="nv">$compile</span><span class="o">)</span>: simplify isolate scope bindings

  Changed the isolate scope binding options to:
    - @attr - attribute binding <span class="o">(</span>including interpolation<span class="o">)</span>
    - <span class="o">=</span>model - by-directional model binding
    - &amp;expr - expression execution binding

  This change simplifies the terminology as well as
  number of choices available to the developer. It
  also supports <span class="nb">local </span>name aliasing from the parent.

  BREAKING CHANGE: isolate scope bindings definition has changed and
  the inject option <span class="k">for </span>the directive controller injection was removed.

  To migrate the code follow the example below:

  Before:

  scope: <span class="o">{</span>
    myAttr: <span class="s1">'attribute'</span>,
    myBind: <span class="s1">'bind'</span>,
    myExpression: <span class="s1">'expression'</span>,
    myEval: <span class="s1">'evaluate'</span>,
    myAccessor: <span class="s1">'accessor'</span>
  <span class="o">}</span>

  After:

  scope: <span class="o">{</span>
    myAttr: <span class="s1">'@'</span>,
    myBind: <span class="s1">'@'</span>,
    myExpression: <span class="s1">'&amp;'</span>,
    // myEval - usually not useful, but <span class="k">in </span>cases where the expression is assignable, you can use <span class="s1">'='</span>
    myAccessor: <span class="s1">'='</span> // <span class="k">in </span>directive<span class="s1">'s template change myAccessor() to myAccessor
  }

  The removed `inject` wasn'</span>t generaly useful <span class="k">for </span>directives so there should be no code using it.
</code></pre></div>    </div>
    <h3 id="参考资料">参考资料</h3>
  </li>
</ul>

<p>[1] <a href="https://juejin.cn/post/6844903635533594632">您必须知道的 Git 分支开发规范</a> https://juejin.cn/post/6844903635533594632</p>

<p>[2] <a href="https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#">Git Commit Message Conventions</a> https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#</p>

<p>[3] <a href="https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines">Angular Git Commit Guidelines</a> https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines</p>

<p>（全文完）</p>

<hr />

<blockquote>
  <p><strong>本文作者</strong>  ：phillee
<strong>发表日期</strong>  ：2021年12月24日
<strong>版权声明</strong>  ：自由转载-非商用-非衍生-保持署名（<a href="https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">创意共享3.0许可协议</a>/<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">CC BY-NC-SA 3.0</a>）。转载请注明出处！
限于本人水平，如果文章和代码有表述不当之处，还请不吝赐教。</p>
</blockquote>]]></content><author><name></name></author><summary type="html"><![CDATA[0.前言]]></summary></entry><entry><title type="html">Python学习笔记之基础语法和函数</title><link href="https://philleer.github.io/blogs.github.io/2021/12/20/Python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8B%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%92%8C%E5%87%BD%E6%95%B0.html" rel="alternate" type="text/html" title="Python学习笔记之基础语法和函数" /><published>2021-12-20T00:00:00+00:00</published><updated>2021-12-20T00:00:00+00:00</updated><id>https://philleer.github.io/blogs.github.io/2021/12/20/Python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8B%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%92%8C%E5%87%BD%E6%95%B0</id><content type="html" xml:base="https://philleer.github.io/blogs.github.io/2021/12/20/Python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8B%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%92%8C%E5%87%BD%E6%95%B0.html"><![CDATA[<!--
- [【Python学习笔记】之基础语法和函数](https://www.cnblogs.com/phillee/p/15645127.html)
#- [【Python学习笔记】之数据结构](https://www.cnblogs.com/phillee/p/15711768.html)
#- [【Python学习笔记】之格式化输入输出](https://www.cnblogs.com/phillee/p/15711921.html)
#- [【Python学习笔记】之基本集成库](https://www.cnblogs.com/phillee/p/15711948.html)
-->

<h3 id="一基础语法和函数相关">一、基础语法和函数相关</h3>

<h4 id="11-len函数">1.1 len()函数</h4>

<p>返回对象（字符、列表、元祖等）的长度或项目个数。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;&gt;&gt;</span><span class="nb">str</span> <span class="o">=</span> <span class="s">"runoob"</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="nb">str</span><span class="p">)</span>             <span class="c1"># 字符串长度
</span><span class="mi">6</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">l</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>               <span class="c1"># 列表元素个数
</span><span class="mi">5</span>
</code></pre></div></div>

<h4 id="12-chr函数">1.2 chr()函数</h4>

<p>用于将一个范围在<code class="language-plaintext highlighter-rouge">range(256)</code>内的整数（也即是 0<code class="language-plaintext highlighter-rouge">~</code>255）转换成对应的<strong>ASCII</strong>码字符。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;&gt;&gt;</span> <span class="k">print</span> <span class="nb">chr</span><span class="p">(</span><span class="mh">0x30</span><span class="p">)</span>    <span class="c1"># 十六进制
</span><span class="mi">0</span>
<span class="o">&gt;&gt;&gt;</span> <span class="k">print</span> <span class="nb">chr</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>    <span class="c1"># 十进制数，ASCII码1表示start of heading，什么也不输出
</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">chr</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="s">'</span><span class="se">\x01</span><span class="s">'</span>
</code></pre></div></div>

<p>与此相对应的有一个函数 <code class="language-plaintext highlighter-rouge">ord()</code>，则是返回单个<strong>ASCII</strong>字符对应的<strong>ASCII</strong>值或<strong>Unicode</strong>值。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;&gt;&gt;</span> <span class="nb">ord</span><span class="p">(</span><span class="s">'d'</span><span class="p">)</span>
<span class="mi">100</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">ord</span><span class="p">(</span><span class="s">'A'</span><span class="p">)</span>
<span class="mi">65</span>
</code></pre></div></div>

<h4 id="13-xrange-函数">1.3 xrange() 函数</h4>

<p><code class="language-plaintext highlighter-rouge">xrange()</code>函数用法与<code class="language-plaintext highlighter-rouge">range()</code>完全相同，所不同的是 xrange() 生成的不是一个数组，而是一个生成器。使用方法如下：</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">1</span> <span class="nb">xrange</span><span class="p">(</span><span class="n">stop</span><span class="p">)</span>
<span class="mi">2</span> <span class="nb">xrange</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">stop</span><span class="p">[,</span> <span class="n">step</span><span class="p">])</span>
</code></pre></div></div>

<p>参数说明：</p>

<ul>
  <li>start: 计数从 start 开始。默认为0。如<code class="language-plaintext highlighter-rouge">xrange(5)</code>等价于<code class="language-plaintext highlighter-rouge">xrange(0， 5)</code>。</li>
  <li>stop: 计数到 stop 结束，但不包括 stop。如<code class="language-plaintext highlighter-rouge">xrange(0， 5)</code>是<code class="language-plaintext highlighter-rouge">[0, 1, 2, 3, 4]</code>没有5。</li>
  <li>step: 步长，默认为1。如<code class="language-plaintext highlighter-rouge">xrange(0， 5)</code>等价于<code class="language-plaintext highlighter-rouge">xrange(0, 5, 1)</code>。</li>
</ul>

<p>range() 方法返回的是一个list对象，它需要开辟专门的空间保存序列中所有的元素。
xrange() 方法返回的是xrange对象，它是一个序列对象，但并不保存序列中的元素。</p>

<p>根据python官方文档的定义，一个序列对象不必要保存所有的元素。
如果只对序列进行读操作，xrange()方法效率较高；但如果要改变序列的元素，或者需要对序列增删元素，那么只能通过range()方法生成一个list对象。</p>

<h4 id="14-with关键字">1.4 with关键字</h4>

<p>如果你有两个想做的操作，你想要这两个操作成对执行，中间插入一段其他的代码，那么使用 with 就是一种很方便的方法。
最经典的例子就是打开一个文件，对文件进行操作然后关闭文件。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">1</span> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'output.txt'</span><span class="p">,</span> <span class="s">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="mi">2</span>     <span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">'Hi there!'</span><span class="p">)</span>
</code></pre></div></div>

<p>上面的with语句会在嵌入的程序运行完后自动关闭文件。好处就是无论嵌套模块如何退出，都可以保证文件被关闭。</p>

<p>如果嵌套模块结束之前有异常发生，系统将在异常被外部异常处理程序捕获之前关闭该文件。
如果嵌套模块中包含有<code class="language-plaintext highlighter-rouge">return</code>语句、<code class="language-plaintext highlighter-rouge">continue</code>语句或者<code class="language-plaintext highlighter-rouge">break</code>语句，<code class="language-plaintext highlighter-rouge">with</code>语句一样可以在跳转之前自动关闭文件。</p>

<h4 id="15-lambda表达式">1.5 lambda表达式</h4>

<p>相对于<code class="language-plaintext highlighter-rouge">def</code>定义的函数而言，<code class="language-plaintext highlighter-rouge">lambda</code>表达式则简单很多，因为其主体是一个表达式而非代码块，
并允许在代码内嵌入一个函数定义，不过一般只能封装有限的逻辑。</p>

<p>如下面的例子所示，lambda表达式定义了一个匿名函数，用于筛选100以内3的倍数，并生成一个列表。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">list</span> <span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span><span class="bp">True</span> <span class="k">if</span> <span class="n">x</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span> <span class="k">else</span> <span class="bp">False</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">)))</span>
</code></pre></div></div>

<p>当然lambda表达式也可以嵌套在函数体内，使用的时候可以用一个变量来接收，如下：</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">make_repeat</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="k">return</span> <span class="k">lambda</span> <span class="n">s</span> <span class="p">:</span> <span class="n">s</span> <span class="o">*</span> <span class="n">n</span>

<span class="n">double</span> <span class="o">=</span> <span class="n">make_repeat</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> 	<span class="c1"># double变量此处是一个函数
</span><span class="k">print</span> <span class="p">(</span><span class="n">double</span><span class="p">(</span><span class="mi">8</span><span class="p">))</span>    		<span class="c1"># 使用double向lambda表达式里的s传一个参数，并得到表达式的结果
</span></code></pre></div></div>

<h4 id="16-内置函数round">1.6 内置函数round()</h4>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">round</span><span class="p">(</span><span class="n">number</span><span class="p">,</span> <span class="n">digits</span><span class="p">)</span>
</code></pre></div></div>

<ul>
  <li>number 给定输入值，即待求解的值。</li>
  <li>digits 指定小数位数，默认为0，此时返回的是int型整数。也就是保留几位小数前提下的四舍五入。</li>
</ul>

<p>该函数根据指定的小数位数对给定输入值进行四舍五入并返回结果。返回值是float类型。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="mf">3.14159</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="mf">3.14159</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="mf">3.14159</span><span class="p">,</span><span class="mi">1</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="mf">3.14159</span><span class="p">,</span><span class="mi">2</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="o">-</span><span class="mf">3.14159</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="o">-</span><span class="mf">3.14159</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="o">-</span><span class="mf">3.14159</span><span class="p">,</span><span class="mi">1</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="o">-</span><span class="mf">3.14159</span><span class="p">,</span><span class="mi">2</span><span class="p">))</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">3</span>			<span class="c1">#round(3.14159)
</span><span class="mf">3.0</span>			<span class="c1">#round(3.14159,0)
</span><span class="mf">3.1</span>			<span class="c1">#round(3.14159,1)
</span><span class="mf">3.14</span>			<span class="c1">#round(3.14159,2)
</span><span class="o">-</span><span class="mi">3</span>			<span class="c1">#round(-3.14159)
</span><span class="o">-</span><span class="mf">3.0</span>			<span class="c1">#round(-3.14159,0)
</span><span class="o">-</span><span class="mf">3.1</span>			<span class="c1">#round(-3.14159,1)
</span><span class="o">-</span><span class="mf">3.14</span>			<span class="c1">#round(-3.14159,2)
</span></code></pre></div></div>

<p>值得注意的是python内置函数<code class="language-plaintext highlighter-rouge">round()</code>采用的<b><font color="Red">银行家舍入法(Banker's rounding)</font></b>。</p>

<p>所谓银行家舍入法即“四舍六入五留双”，是IEEE 754标准推荐的舍入标准，可以概括为：<b>“四舍六入五考虑，五后非零就进一，五后皆零看奇偶，五前为偶应舍去，五前为奇要进一”</b>。</p>

<p>具体计算规则如下：</p>
<ul>
  <li>（1）被修约的数字小于或等于4时，该数字舍去；</li>
  <li>（2）被修约的数字大于或等于6时，则进位；</li>
  <li>（3）被修约的数字等于5时，先看5后面是否有不为“0”的任何数，如果有则进位；如果没有接着看5前面的数字，若是奇数则进位，若是偶数则将5舍掉，即修约后末尾数字都为偶数。</li>
</ul>

<p>可以结合如下示例理解。</p>

<ul>
  <li>
    <p>示例1：求给定输入的round()结果，默认只保留整数部分。</p>

    <table>
      <thead>
        <tr>
          <th style="text-align: center">val</th>
          <th style="text-align: center">1.5</th>
          <th style="text-align: center">1.50</th>
          <th style="text-align: center">1.51</th>
          <th style="text-align: center">1.55</th>
          <th style="text-align: center">1.59</th>
          <th style="text-align: center">2.5</th>
          <th style="text-align: center">2.50</th>
          <th style="text-align: center">2.51</th>
          <th style="text-align: center">2.55</th>
          <th style="text-align: center">2.59</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td style="text-align: center">round(val)</td>
          <td style="text-align: center"><b>2</b></td>
          <td style="text-align: center"><b>2</b></td>
          <td style="text-align: center"><b>2</b></td>
          <td style="text-align: center"><b>2</b></td>
          <td style="text-align: center"><b>2</b></td>
          <td style="text-align: center"><b><font color="Red">2</font></b></td>
          <td style="text-align: center"><b><font color="Red">2</font></b></td>
          <td style="text-align: center"><b><font color="Red">3</font></b></td>
          <td style="text-align: center"><b>3</b></td>
          <td style="text-align: center"><b>3</b></td>
        </tr>
      </tbody>
    </table>
  </li>
  <li>
    <p>示例2：求给定输入的round()结果，保留小数点后两位有效数字。</p>

    <table>
      <thead>
        <tr>
          <th style="text-align: center">val</th>
          <th style="text-align: center">9.8249</th>
          <th style="text-align: center">9.8267</th>
          <th style="text-align: center">9.8350</th>
          <th style="text-align: center">9.83501</th>
          <th style="text-align: center">9.8250</th>
          <th style="text-align: center">9.82501</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td style="text-align: center">round(val, 2)</td>
          <td style="text-align: center">9.82</td>
          <td style="text-align: center">9.83</td>
          <td style="text-align: center">9.84</td>
          <td style="text-align: center">9.84</td>
          <td style="text-align: center">9.82</td>
          <td style="text-align: center">9.83</td>
        </tr>
      </tbody>
    </table>
  </li>
</ul>

<blockquote>
  <注>：按照四舍六入五留双规则进行数字修约时，应一次性修约到指定位数，不可以进行多次修约。例如将数字10.2749945001修约为四位有效数字，应一步到位：10.2749945001=10.27（正确）。
如果按照四舍六入五留双规则分步修约将得到错误结果：10.2749945001=10.274995=10.275=10.28（错误）。
</注>
</blockquote>

<h4 id="17-内置函数int">1.7 内置函数int()</h4>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
</code></pre></div></div>

<ul>
  <li>value	可以被转换成int型整数的一个数或者一个字符串。</li>
  <li>base	用于表示进制的数值。可以是2表示二进制、8表示八进制，16表示十六进制等。默认是10，表示转换成十进制的结果。</li>
</ul>

<h5 id="a-当输入为一个数时">(a) 当输入为一个数时</h5>

<p>可以是浮点数，也可以是整数。相比于math.ceil()、math.floor()、round()等函数而言运算比较简单粗暴，直接截断舍弃小数部分，返回整数部分。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="mf">25.5</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="mf">20.3</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="mf">30.7</span><span class="p">))</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">25</span>	<span class="c1">#int(25.5)
</span><span class="mi">20</span>	<span class="c1">#int(20.3)
</span><span class="mi">30</span>	<span class="c1">#int(30.7)
</span></code></pre></div></div>

<h5 id="b-当输入为字符串时">(b) 当输入为字符串时</h5>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="s">"11"</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="s">"15"</span><span class="p">))</span>

<span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="s">'1'</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="s">'100'</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>

<span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="s">'7'</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="s">'500'</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span>

<span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="s">'A'</span><span class="p">,</span> <span class="mi">16</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="s">'10'</span><span class="p">,</span> <span class="mi">16</span><span class="p">))</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">11</span>	<span class="c1">#int("11")
</span><span class="mi">15</span> 	<span class="c1">#int("15")
</span>
<span class="mi">1</span> 	<span class="c1">#int('1', 2)
</span><span class="mi">4</span>	<span class="c1">#int('100', 2)
</span>
<span class="mi">7</span>	<span class="c1">#int('7', 8)
</span><span class="mi">320</span> 	<span class="c1">#int('500', 8)
</span>
<span class="mi">10</span> 	<span class="c1">#int('A', 16)
</span><span class="mi">16</span> 	<span class="c1">#int('10', 16)
</span></code></pre></div></div>

<h4 id="18-算术运算符">1.8 算术运算符<code class="language-plaintext highlighter-rouge">//</code></h4>

<p>python文档中称之为<b><font color="Red">floor division operator</font></b>，直译过来即地板除，而且还特别声明了无论操作数是整型还是浮点型，都执行的是floor操作。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="mi">5</span><span class="o">//</span><span class="mi">2</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="mi">5</span><span class="o">//</span><span class="mf">2.0</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="mf">5.0</span><span class="o">//</span><span class="mf">2.0</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="mf">5.0</span><span class="o">//-</span><span class="mf">2.0</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="o">-</span><span class="mf">5.0</span><span class="o">//</span><span class="mf">2.0</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="o">-</span><span class="mf">5.0</span><span class="o">//-</span><span class="mf">2.0</span><span class="p">)</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">2</span>		<span class="c1">#5//2
</span><span class="mf">2.0</span>		<span class="c1">#5//2.0
</span><span class="mf">2.0</span>		<span class="c1">#5.0//2.0
</span><span class="o">-</span><span class="mf">3.0</span>		<span class="c1">#5.0//-2.0
</span><span class="o">-</span><span class="mf">3.0</span>		<span class="c1">#-5.0//2.0
</span><span class="mf">2.0</span>		<span class="c1">#-5.0//-2.0
</span></code></pre></div></div>

<h4 id="19-内置函数eval">1.9 内置函数eval()</h4>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">eval</span><span class="p">(</span><span class="n">expression</span><span class="p">[,</span> <span class="nb">globals</span><span class="p">[,</span> <span class="nb">locals</span><span class="p">]])</span>
</code></pre></div></div>

<p>该函数基本功能是将给定字符串当作有效表达式来求值，并返回计算结果。</p>

<p>函数参数是字符串以及可选的全局。如果给出globals，则必须是以字典形式给出的全局变量集。
locals可以是任何一种映射对象(mapping object)。</p>

<p>如果给定输入是字符串，开头和结尾的空格及制表位都会被跳过。</p>

<h5 id="191-可以当作计算器使用">1.9.1 可以当作计算器使用</h5>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
<span class="nb">eval</span><span class="p">(</span><span class="s">'x+1'</span><span class="p">)</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">2</span>	<span class="c1">#eval('x+1')
</span></code></pre></div></div>

<h5 id="192-可以将listtupledict与string相互转化">1.9.2 可以将list/tuple/dict与string相互转化</h5>

<ul>
  <li>(a) 字符串转换成列表</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">str_list</span> <span class="o">=</span> <span class="s">"[[1,2], [3,4], [5,6]]"</span>
<span class="nb">type</span><span class="p">(</span><span class="n">str_list</span><span class="p">)</span>
<span class="n">list_from_str</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">str_list</span><span class="p">)</span>
<span class="nb">type</span><span class="p">(</span><span class="n">list_from_str</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">list_from_str</span><span class="p">)</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&lt;</span><span class="k">class</span> <span class="err">'</span><span class="nc">str</span><span class="s">'&gt;	#type(str_list)
&lt;class '</span><span class="nb">list</span><span class="s">'&gt;	#type(list_from_str)
[[1, 2], [3, 4], [5, 6]]	#list_from_str
</span></code></pre></div></div>

<ul>
  <li>(b) 字符串转换成元组</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">str_tup</span> <span class="o">=</span> <span class="s">"([1,2], [3,4], (5,6))"</span>
<span class="nb">type</span><span class="p">(</span><span class="n">str_tup</span><span class="p">)</span>
<span class="n">tup_from_str</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">str_tup</span><span class="p">)</span>
<span class="nb">type</span><span class="p">(</span><span class="n">tup_from_str</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">tup_from_str</span><span class="p">)</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&lt;</span><span class="k">class</span> <span class="err">'</span><span class="nc">str</span><span class="s">'&gt;
&lt;class '</span><span class="nb">tuple</span><span class="s">'&gt;
([1, 2], [3, 4], (5, 6))
</span></code></pre></div></div>

<ul>
  <li>(c) 字符串转换成字典</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">str_dict</span> <span class="o">=</span> <span class="s">"{1:'a', 2:'b', 3:'c'}"</span>
<span class="nb">type</span><span class="p">(</span><span class="n">str_dict</span><span class="p">)</span>
<span class="n">dict_from_str</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">str_dict</span><span class="p">)</span>
<span class="nb">type</span><span class="p">(</span><span class="n">dict_from_str</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">dict_from_str</span><span class="p">)</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&lt;</span><span class="k">class</span> <span class="err">'</span><span class="nc">str</span><span class="s">'&gt;
&lt;class '</span><span class="nb">dict</span><span class="s">'&gt;
{1: '</span><span class="n">a</span><span class="s">', 2: '</span><span class="sa">b</span><span class="s">', 3: '</span><span class="n">c</span><span class="s">'}
</span></code></pre></div></div>

<ul>
  <li>(d) 字典转换成字符串</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">str_transfered_from_dict</span><span class="o">=</span><span class="s">'dict_from_str'</span>
<span class="nb">type</span><span class="p">(</span><span class="n">str_transfered_from_dict</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">str_transfered_from_dict</span><span class="p">)</span>
<span class="n">dict_from_transfered_str</span><span class="o">=</span><span class="nb">eval</span><span class="p">(</span><span class="n">str_transfered_from_dict</span><span class="p">)</span>
<span class="nb">type</span><span class="p">(</span><span class="n">dict_from_transfered_str</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">dict_from_transfered_str</span><span class="p">)</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&lt;</span><span class="k">class</span> <span class="err">'</span><span class="nc">str</span><span class="s">'&gt;
dict_from_str
&lt;class '</span><span class="nb">dict</span><span class="s">'&gt;
{1: '</span><span class="n">a</span><span class="s">', 2: '</span><span class="sa">b</span><span class="s">', 3: '</span><span class="n">c</span><span class="s">'}
</span></code></pre></div></div>

<p>当然还有一些更高阶的用法，用到了再说。</p>

<p>（全文完）</p>

<hr />

<h3 id="参考资料">参考资料</h3>

<p>[1] <a href="https://www.cnblogs.com/shixisheng/p/7089930.html">PYTHON中XRANGE和RANGE</a> https://www.cnblogs.com/shixisheng/p/7089930.html</p>

<p>[2] <a href="https://www.cnblogs.com/jydeng/p/4145188.html">python lambda表达式</a> https://www.cnblogs.com/jydeng/p/4145188.html</p>

<p>[3] <a href="https://docs.python.org/3/whatsnew/3.0.html">What’s New In Python 3.0</a> https://docs.python.org/3/whatsnew/3.0.html</p>

<p>[4] <a href="https://stackoverflow.com/questions/10825926/python-3-x-rounding-behavior">Python 3.x rounding behavior</a> https://stackoverflow.com/questions/10825926/python-3-x-rounding-behavior</p>

<p>[5] <a href="https://stackoverflow.com/questions/183853/what-is-the-difference-between-and-when-used-for-division">What is the difference between ‘/’ and ‘//’ when used for division?</a> https://stackoverflow.com/questions/183853/what-is-the-difference-between-and-when-used-for-division</p>

<p>[6] <a href="https://www.programiz.com/python-programming/methods/built-in/eval">Python eval()</a> https://www.programiz.com/python-programming/methods/built-in/eval</p>

<p>[7] <a href="https://blog.csdn.net/maozexijr/article/details/78563531">为什么银行家舍入是合理的？</a> https://blog.csdn.net/maozexijr/article/details/78563531</p>

<p>[8] <a href="https://en.wikipedia.org/wiki/Rounding#Round_half_to_even">Round half to even</a> https://en.wikipedia.org/wiki/Rounding#Round_half_to_even</p>

<p>[9] <a href="https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules">Rounding rules</a> https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules</p>

<p>[10] <a href="https://juejin.cn/post/6844904055953702919">从“四舍五入”到“奇进偶舍”</a> https://juejin.cn/post/6844904055953702919</p>

<p>[11] <a href="https://youwuqiong.top/10276.html">利息被银行四舍五入后，你到底是赚了还是亏了？答案和想的不太一样｜把科学带回家</a> https://youwuqiong.top/10276.html</p>

<blockquote>
  <p><strong>本文作者</strong>  ：phillee</p>

  <p><strong>发表日期</strong>  ：2021年12月20日</p>

  <p><strong>版权声明</strong>  ：自由转载-非商用-非衍生-保持署名（<a href="https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh">创意共享3.0许可协议</a>/<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">CC BY-NC-SA 3.0</a>）。转载请注明出处！</p>

  <p>限于本人水平，如果文章和代码有表述不当之处，还请不吝赐教。</p>
</blockquote>]]></content><author><name></name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">在项目中使用 FFmpeg 库</title><link href="https://philleer.github.io/blogs.github.io/2021/03/23/Use-FFmpeg-libs-in-our-project.html" rel="alternate" type="text/html" title="在项目中使用 FFmpeg 库" /><published>2021-03-23T00:00:00+00:00</published><updated>2021-03-23T00:00:00+00:00</updated><id>https://philleer.github.io/blogs.github.io/2021/03/23/Use-FFmpeg-libs-in-our-project</id><content type="html" xml:base="https://philleer.github.io/blogs.github.io/2021/03/23/Use-FFmpeg-libs-in-our-project.html"><![CDATA[<h3 id="一引言">一、引言</h3>

<p>首先需要把 <code class="language-plaintext highlighter-rouge">FFmpeg</code> 安装到指定路径，安装过程。安装可参考官方指南：<a href="https://trac.ffmpeg.org/wiki/CompilationGuide">https://trac.ffmpeg.org/wiki/CompilationGuide</a>。</p>

<p>要使用 <code class="language-plaintext highlighter-rouge">FFmpeg</code> 就必须引用它的头文件，以及在链接中使用它的静态或动态库文件。</p>

<p>本文即是讲述关于如何引用该库的头文件以及使用 <code class="language-plaintext highlighter-rouge">CMake</code> 来链接库文件构建项目。</p>

<h3 id="二在项目文件中引用头文件">二、在项目文件中引用头文件</h3>

<p>面向对象的 <code class="language-plaintext highlighter-rouge">C++</code> 本身是支持函数重载的，而面向过程的 <code class="language-plaintext highlighter-rouge">C</code> 语言不支持重载。</p>

<p>不同的设计理念使得同一个函数在两种语言编译后的符号表中的签名是不同的，进而在链接过程中如果不加 <code class="language-plaintext highlighter-rouge">extern "C"</code> 关键字将会链接到 <code class="language-plaintext highlighter-rouge">C++</code> 格式的方法签名，而加了 <code class="language-plaintext highlighter-rouge">extern "C"</code> 关键字会寻找 <code class="language-plaintext highlighter-rouge">C</code> 格式的方法签名。</p>

<p><code class="language-plaintext highlighter-rouge">FFmpeg</code> 是 <code class="language-plaintext highlighter-rouge">C</code> 语言书写的，所以我们在 <code class="language-plaintext highlighter-rouge">C++</code> 项目中引用 <code class="language-plaintext highlighter-rouge">FFmpeg</code> 时必须加上 <code class="language-plaintext highlighter-rouge">extern "C"</code> 关键字。</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
 * Main file: main.cc
 *
 * Description:
 *	Try to do some avcodec operations by invoking functions defined in ffmpeg.
 */</span>

<span class="cp">#include</span> <span class="cpf">&lt;cstdio&gt;</span><span class="cp">
</span>
<span class="cp">#ifdef __APPLE__
</span><span class="k">extern</span> <span class="s">"C"</span> <span class="p">{</span>
<span class="cp">#include</span> <span class="cpf">"libavcodec/avcodec.h"</span><span class="cp">
#include</span> <span class="cpf">"libavformat/avformat.h"</span><span class="cp">
#include</span> <span class="cpf">"libswscale/swscale.h"</span><span class="cp">
#include</span> <span class="cpf">"libswresample/swresample.h"</span><span class="cp">
#include</span> <span class="cpf">"libavutil/pixdesc.h"</span><span class="cp">
</span><span class="p">}</span>
<span class="cp">#endif
</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
    <span class="n">avformat_network_init</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Please set the file path to open...</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"open accompany file %s ...</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>

    <span class="n">AVFormatContext</span> <span class="o">*</span><span class="n">formatCtx</span> <span class="o">=</span> <span class="n">avformat_alloc_context</span><span class="p">();</span>

    <span class="c1">// Do something</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="三设置并链接相应的库">三、设置并链接相应的库</h3>

<p>在 <code class="language-plaintext highlighter-rouge">CMakeLists.txt</code> 中使用 <code class="language-plaintext highlighter-rouge">INCLUDE_DIRECTORIES</code> 设置 <code class="language-plaintext highlighter-rouge">FFmpeg</code> 头文件所在路径。</p>

<p>使用 <code class="language-plaintext highlighter-rouge">LINK_DIRECTORIES</code> 设置库文件所在路径，并在 <code class="language-plaintext highlighter-rouge">TARGET_LINK_LIBRARIES</code> 中链接所需要的库文件。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># CMakeLists.txt
</span><span class="n">CMAKE_MINIMUM_REQUIRED</span><span class="p">(</span><span class="n">VERSION</span> <span class="mf">3.0</span><span class="p">)</span>

<span class="n">PROJECT</span><span class="p">(</span><span class="n">FFMPEG_TEST</span><span class="p">)</span>

<span class="n">SET</span><span class="p">(</span><span class="n">CMAKE_BUILD_TYPE</span> <span class="n">RELEASE</span><span class="p">)</span>
<span class="n">SET</span><span class="p">(</span><span class="n">CMAKE_CXX_STANDARD</span> <span class="mi">11</span><span class="p">)</span>
<span class="n">SET</span><span class="p">(</span><span class="n">CMAKE_CXX_FLAGS</span> <span class="s">"${CMAKE_CXX_FLAGS} -std=c++11 -Wall"</span><span class="p">)</span>
<span class="n">SET</span><span class="p">(</span><span class="n">FFmpeg_DIR</span> <span class="o">/</span><span class="n">Users</span><span class="o">/</span><span class="n">phillee</span><span class="o">/</span><span class="n">ffmpeg</span><span class="p">)</span>

<span class="n">INCLUDE_DIRECTORIES</span><span class="p">(</span><span class="err">$</span><span class="p">{</span><span class="n">FFmpeg_DIR</span><span class="p">}</span><span class="o">/</span><span class="n">ffmpeg</span><span class="o">-</span><span class="nb">bin</span><span class="o">/</span><span class="n">include</span><span class="p">)</span>
<span class="n">LINK_DIRECTORIES</span><span class="p">(</span><span class="err">$</span><span class="p">{</span><span class="n">FFmpeg_DIR</span><span class="p">}</span><span class="o">/</span><span class="n">ffmpeg</span><span class="o">-</span><span class="nb">bin</span><span class="o">/</span><span class="n">lib</span><span class="p">)</span>

<span class="c1"># Messages to show
</span><span class="n">MESSAGE</span><span class="p">(</span><span class="n">STATUS</span> <span class="s">"** Customized settings are shown as below **"</span><span class="p">)</span>
<span class="n">MESSAGE</span><span class="p">(</span><span class="n">STATUS</span> <span class="s">"</span><span class="se">\t</span><span class="s">CMAKE BUILD TYPE: ${CMAKE_BUILD_TYPE}"</span><span class="p">)</span>
<span class="n">MESSAGE</span><span class="p">(</span><span class="n">STATUS</span> <span class="s">"</span><span class="se">\t</span><span class="s">FFmpeg include directory: ${FFmpeg_DIR}/ffmpeg-bin/include"</span><span class="p">)</span>
<span class="n">MESSAGE</span><span class="p">(</span><span class="n">STATUS</span> <span class="s">"</span><span class="se">\t</span><span class="s">FFmpeg library directory: ${FFmpeg_DIR}/ffmpeg-bin/lib"</span><span class="p">)</span>

<span class="n">ADD_EXECUTABLE</span><span class="p">(</span><span class="n">ffmpeg_test</span> <span class="n">main</span><span class="p">.</span><span class="n">cc</span><span class="p">)</span>

<span class="n">TARGET_LINK_LIBRARIES</span><span class="p">(</span><span class="n">ffmpeg_test</span>
    <span class="n">avcodec</span>
    <span class="n">avformat</span>
    <span class="n">avutil</span>
    <span class="n">postproc</span>
    <span class="n">swresample</span>
    <span class="n">swscale</span>
    <span class="p">)</span>
</code></pre></div></div>

<p>设置完成后 <code class="language-plaintext highlighter-rouge">cmake</code> 和 <code class="language-plaintext highlighter-rouge">make</code> 编译即可成功生成可执行文件。</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">mkdir </span>build <span class="o">&amp;&amp;</span> <span class="nb">cd </span>build

<span class="nv">$ </span>cmake .. <span class="o">&amp;&amp;</span> make
</code></pre></div></div>]]></content><author><name></name></author><summary type="html"><![CDATA[一、引言]]></summary></entry><entry><title type="html">CMake基础语法及应用</title><link href="https://philleer.github.io/blogs.github.io/2021/03/22/CMake%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%8F%8A%E5%BA%94%E7%94%A8.html" rel="alternate" type="text/html" title="CMake基础语法及应用" /><published>2021-03-22T00:00:00+00:00</published><updated>2021-03-22T00:00:00+00:00</updated><id>https://philleer.github.io/blogs.github.io/2021/03/22/CMake%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%8F%8A%E5%BA%94%E7%94%A8</id><content type="html" xml:base="https://philleer.github.io/blogs.github.io/2021/03/22/CMake%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%8F%8A%E5%BA%94%E7%94%A8.html"><![CDATA[<p><strong>本文目录</strong></p>

<ol id="markdown-toc">
  <li><a href="#一cmakefiles文件书写语法" id="markdown-toc-一cmakefiles文件书写语法">一、CMakeFiles文件书写语法</a>    <ol>
      <li><a href="#1-cmake中条件判断语句" id="markdown-toc-1-cmake中条件判断语句">1. CMake中条件判断语句</a></li>
      <li><a href="#2-设置编译选项" id="markdown-toc-2-设置编译选项">2. 设置编译选项</a></li>
      <li><a href="#3-打印信息到屏幕" id="markdown-toc-3-打印信息到屏幕">3. 打印信息到屏幕</a></li>
    </ol>
  </li>
  <li><a href="#二cmake编译命令行参数详解" id="markdown-toc-二cmake编译命令行参数详解">二、cmake编译命令行参数详解</a>    <ol>
      <li><a href="#1-如果想要将项目编译成动态链接库的形式可以在命令行通过参数控制" id="markdown-toc-1-如果想要将项目编译成动态链接库的形式可以在命令行通过参数控制">1. 如果想要将项目编译成动态链接库的形式，可以在命令行通过参数控制</a></li>
      <li><a href="#2-指定编译安装路径" id="markdown-toc-2-指定编译安装路径">2. 指定编译安装路径</a></li>
    </ol>
  </li>
  <li><a href="#三cmake项目应用案例" id="markdown-toc-三cmake项目应用案例">三、CMake项目应用案例</a>    <ol>
      <li><a href="#1下载并安装eigenceres-solver等数学运算库" id="markdown-toc-1下载并安装eigenceres-solver等数学运算库">1.下载并安装eigen、ceres-solver等数学运算库</a></li>
    </ol>
  </li>
  <li><a href="#参考资料" id="markdown-toc-参考资料">参考资料</a></li>
</ol>

<h3 id="一cmakefiles文件书写语法">一、CMakeFiles文件书写语法</h3>

<h4 id="1-cmake中条件判断语句">1. CMake中条件判断语句</h4>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="o">&lt;</span><span class="n">constant</span><span class="o">&gt;</span><span class="p">)</span>
<span class="p">...</span>
<span class="k">else</span><span class="p">()</span>
<span class="p">...</span>
<span class="n">endif</span><span class="p">()</span>
</code></pre></div></div>

<p>当 <code class="language-plaintext highlighter-rouge">constant</code> 为 <code class="language-plaintext highlighter-rouge">1/ON/YES/TRUE/Y/Non-zero</code> 时判别为真；</p>

<p>当 <code class="language-plaintext highlighter-rouge">constant</code> 为 <code class="language-plaintext highlighter-rouge">0/OFF/NO/FALSE/N/IGNORE/NOTFOUND</code> 或者为空字符串 或后缀为 <code class="language-plaintext highlighter-rouge">-NOTFOUND</code> 时判断为假。</p>

<p>大小写敏感，当不是上述列举出来的这些常量时，作为变量对待。</p>

<h4 id="2-设置编译选项">2. 设置编译选项</h4>

<p>CMake 中可以通过 <code class="language-plaintext highlighter-rouge">CMAKE_BUILD_TYPE</code> 来对编译方式进行控制，使产生 <code class="language-plaintext highlighter-rouge">Debug</code> 类型的可执行程序或者 <code class="language-plaintext highlighter-rouge">Release</code> 类型的可执行程序，方便我们进行调试或者优化。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">SET</span><span class="p">(</span><span class="n">CMAKE_BUILD_TYPE</span> <span class="s">"MYTYPE"</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">MYTYPE</code> 可以选择的类型有：<code class="language-plaintext highlighter-rouge">空, Debug, Release, RelWithDebInfo, MinSizeRel</code>。</p>

<h4 id="3-打印信息到屏幕">3. 打印信息到屏幕</h4>

<p>当我们需要在文件中向屏幕输出一些提示信息或者警告，可以使用 <code class="language-plaintext highlighter-rouge">MESSAGE</code> 来实现。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">MESSAGE</span><span class="p">([</span><span class="n">OPTION</span><span class="p">]</span> <span class="s">"Description of the message"</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">OPTION</code> 可以是 <code class="language-plaintext highlighter-rouge">STATUS/WARNING/FATAL_ERROR</code> 中任意一个，也可以保持缺省状态。默认是<code class="language-plaintext highlighter-rouge">STATUS</code>。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">MESSAGE</span><span class="p">(</span><span class="n">STATUS</span> <span class="s">"Status test!"</span><span class="p">)</span>
<span class="n">MESSAGE</span><span class="p">(</span><span class="n">WARNING</span> <span class="s">"Waning test!"</span><span class="p">)</span>
<span class="n">MESSAGE</span><span class="p">(</span><span class="n">FATAL_ERROR</span> <span class="s">"Fatal error test!"</span><span class="p">)</span>
</code></pre></div></div>

<p>三种类型的输出显示如下，当设置为 <code class="language-plaintext highlighter-rouge">FATAL_ERROR</code> 并触发输出时，会使得 <code class="language-plaintext highlighter-rouge">cmake</code> 被终止。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="n">Status</span> <span class="n">test</span><span class="err">!</span>
<span class="n">CMake</span> <span class="nb">Warning</span> <span class="n">at</span> <span class="n">CMakeLists</span><span class="p">.</span><span class="n">txt</span><span class="p">:</span><span class="mi">16</span> <span class="p">(</span><span class="n">MESSAGE</span><span class="p">):</span>
  <span class="n">Waning</span> <span class="n">test</span><span class="err">!</span>


<span class="n">CMake</span> <span class="n">Error</span> <span class="n">at</span> <span class="n">CMakeLists</span><span class="p">.</span><span class="n">txt</span><span class="p">:</span><span class="mi">17</span> <span class="p">(</span><span class="n">MESSAGE</span><span class="p">):</span>
  <span class="n">Fatal</span> <span class="n">error</span> <span class="n">test</span><span class="err">!</span>


<span class="o">--</span> <span class="n">Configuring</span> <span class="n">incomplete</span><span class="p">,</span> <span class="n">errors</span> <span class="n">occurred</span><span class="err">!</span>
</code></pre></div></div>

<h3 id="二cmake编译命令行参数详解">二、cmake编译命令行参数详解</h3>

<h4 id="1-如果想要将项目编译成动态链接库的形式可以在命令行通过参数控制">1. 如果想要将项目编译成动态链接库的形式，可以在命令行通过参数控制</h4>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cmake</span> <span class="o">-</span><span class="n">DBUILD_SHARED_LIBS</span><span class="o">=</span><span class="n">ON</span> <span class="p">..</span>
</code></pre></div></div>

<h4 id="2-指定编译安装路径">2. 指定编译安装路径</h4>

<p>通过在编译命令行中使用指令 <code class="language-plaintext highlighter-rouge">CMAKE_INSTALL_PREFIX</code> 来控制。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cmake</span> <span class="o">-</span><span class="n">DCMAKE_INSTALL_PREFIX</span><span class="o">=/</span><span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">install</span> <span class="p">..</span>
</code></pre></div></div>

<h3 id="三cmake项目应用案例">三、CMake项目应用案例</h3>

<h4 id="1下载并安装eigenceres-solver等数学运算库">1.下载并安装eigen、ceres-solver等数学运算库</h4>

<p>可以参考openMVS build <a href="https://github.com/cdcseacave/openMVS/wiki/Building">wiki</a></p>

<p><strong>TODO</strong></p>

<ul>
  <li>Improve compile time using forward declaration of options</li>
  <li>借鉴并学习 <code class="language-plaintext highlighter-rouge">COLMAP</code> 提升编译速度的技巧！</li>
</ul>

<p><strong>附：各种不同的GPU架构对应的 sm 标志</strong></p>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210322-cmake-01.png#pic_center" alt="GPU_SM" /></p>

<p>(全文完)</p>

<hr />

<h3 id="参考资料">参考资料</h3>

<p>[1] <a href="https://blog.csdn.net/laolu1573/article/details/60573511">Cmake中查找并使用其他程序库</a> <a href="https://blog.csdn.net/laolu1573/article/details/60573511">https://blog.csdn.net/laolu1573/article/details/60573511</a></p>

<p>[2] <a href="https://blog.csdn.net/billbliss/article/details/88585171">配置eigen3和ceres为thirdparty</a> <a href="https://blog.csdn.net/billbliss/article/details/88585171">https://blog.csdn.net/billbliss/article/details/88585171</a></p>

<p>[3] <a href="https://wagonhelm.github.io/articles/2018-03/detecting-cuda-capability-with-cmake">Detecting Cuda Architecture required by CMake using NVCC</a> <a href="https://wagonhelm.github.io/articles/2018-03/detecting-cuda-capability-with-cmake">https://wagonhelm.github.io/articles/2018-03/detecting-cuda-capability-with-cmake</a></p>

<p>[4] <a href="http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/">Matching SM architectures (CUDA arch and CUDA gencode) for various NVIDIA cards</a><a href="http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/">http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/</a></p>]]></content><author><name></name></author><summary type="html"><![CDATA[本文目录]]></summary></entry><entry><title type="html">Apple ID从中国大陆区切换为美国区</title><link href="https://philleer.github.io/blogs.github.io/2021/01/16/appleid.html" rel="alternate" type="text/html" title="Apple ID从中国大陆区切换为美国区" /><published>2021-01-16T00:00:00+00:00</published><updated>2021-01-16T00:00:00+00:00</updated><id>https://philleer.github.io/blogs.github.io/2021/01/16/appleid</id><content type="html" xml:base="https://philleer.github.io/blogs.github.io/2021/01/16/appleid.html"><![CDATA[<p><strong>本文目录</strong></p>

<ol id="markdown-toc">
  <li><a href="#登陆账号" id="markdown-toc-登陆账号">登陆账号</a></li>
  <li><a href="#编辑账户信息" id="markdown-toc-编辑账户信息">编辑账户信息</a></li>
  <li><a href="#输入相关信息" id="markdown-toc-输入相关信息">输入相关信息</a></li>
  <li><a href="#参考资料" id="markdown-toc-参考资料">参考资料</a></li>
</ol>

<p>有时候我们需要从App Store下载某个应用，比如我要使用Oculus的客户端，但该应用在中国大陆没有上架，美国区账号却可以下载到。这时如果你有美国区的Apple ID账号当然可以直接切换使用，而如果没有另外的账号又想下载该应用，就需要切换Apple ID所属区域。</p>

<h2 id="登陆账号">登陆账号</h2>

<p>进入苹果官网账号登陆页面 https://appleid.apple.com/</p>

<p>如下图所示</p>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210116-appleid_01.png" alt="" title="苹果官网账号登录页面-输入账号" /></p>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210116-appleid_02.png" alt="" title="苹果官网账号登录页面-输入密码" /></p>

<p>这时会出现验证信息，这是苹果为了确保账号安全性而进行的操作。</p>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210116-appleid_03.png" alt="" title="苹果官网账号登录验证" /></p>

<p>iPhone手机端或Mac电脑端会弹出如下的对话框，确认并将弹出的验证码填入上图网页验证码位置处。</p>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210116-appleid_04.jpg" alt="" title="iPhone手机端登陆验证" />
<img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210116-appleid_05.jpg" alt="" title="iPhone手机端验证码" /></p>

<h2 id="编辑账户信息">编辑账户信息</h2>

<p>上述操作完成后会进入到如下的界面</p>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210116-appleid_06.png" alt="" title="账户信息界面" /></p>

<p>点击右侧的 “Edit” 开始编辑，点击 COUNTRY/REGION 下拉菜单选择“United States”</p>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210116-appleid_07.png" alt="" title="改变所属地区" /></p>

<p>这时会弹出是否确认改变的弹窗，点击继续</p>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210116-appleid_08.png" alt="" title="继续更新操作" /></p>

<p>此时界面如下所示</p>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210116-appleid_09.png" alt="" title="当前界面" /></p>

<h2 id="输入相关信息">输入相关信息</h2>

<p>可以按照下图中的信息直接输入</p>

<p><img src="https://raw.githubusercontent.com/philleer/blogs.github.io/refs/heads/master/images/20210116-appleid_10.png" alt="" title="美区账号信息示例" /></p>

<p>可供参考的填写内容如下</p>
<pre><code class="language-plain">付款方式: None

州: New York
邮编: 10022
电话: 9176212121

州: State of Montana
邮递区号: 59601
电话: 4062047893

城市: Covina
州: CA
邮递区号: 91723
电话: 6263396261

城市: Glendora
州: CA
邮递区号: 91740
电话: 9093949899
</code></pre>

<p>好了，之后再登陆iPhone App Store刷新之后即可搜索到所需App了，整个过程其实也挺简单的。</p>

<p>还有一点需要注意一下，无论是买的别人的美区账号，还是自己把账号改成美区，都最好只在App Store登陆，不要登陆iCloud，据说是会被别人锁设备（咱也不知道为啥，反正注意就是了）。</p>

<hr />

<h2 id="参考资料">参考资料</h2>

<p>[1] <a href="https://support.apple.com/zh-cn/HT201389" title="更改 Apple ID 国家或地区">更改 Apple ID 国家或地区</a></p>

<p>[2] https://zhuanlan.zhihu.com/p/347463724</p>

<p>[3] https://zhuanlan.zhihu.com/p/367821925</p>

<p>（全文完）</p>]]></content><author><name></name></author><summary type="html"><![CDATA[本文目录]]></summary></entry></feed>