{
    "version": "https://jsonfeed.org/version/1",
    "title": "昨日已逝，明日未知，而今日为金",
    "subtitle": "",
    "icon": "https://littlestory1.github.io/images/favicon.ico",
    "description": "",
    "home_page_url": "https://littlestory1.github.io",
    "items": [
        {
            "id": "https://littlestory1.github.io/2024/03/19/baguwen/0-2-%E5%B5%8C%E8%BD%AF%E7%AC%94%E8%AF%95%E9%9D%A2%E8%AF%95-%E7%BB%8F%E5%85%B8/",
            "url": "https://littlestory1.github.io/2024/03/19/baguwen/0-2-%E5%B5%8C%E8%BD%AF%E7%AC%94%E8%AF%95%E9%9D%A2%E8%AF%95-%E7%BB%8F%E5%85%B8/",
            "title": "0-2-嵌软笔试面试-经典",
            "date_published": "2024-03-18T17:18:25.286Z",
            "content_html": "<p><img data-src=\"1.jpg\" alt></p>\n<h2 id=\"嵌软笔试面试经典题\"><a class=\"anchor\" href=\"#嵌软笔试面试经典题\">#</a> 嵌软笔试面试 —— 经典题</h2>\n<h3 id=\"零值\"><a class=\"anchor\" href=\"#零值\">#</a> 零值</h3>\n<blockquote>\n<p>1、请填写 bool , float, 指针变量 与 “零值” 比较的 if 语句。</p>\n<p>提示：这里 “零值” 可以是 0, 0.0 , FALSE 或者 “空指针”。例如 int 变量 n 与 “零值” 比较的 if 语句为： if ( n == 0 )   if ( n != 0 ) 以此类推。</p>\n<p><strong>（1）</strong> 请写出 bool flag 与 “零值” 比较的 if 语句：</p>\n<p>【标准答案】if (flag)  if ( !flag )</p>\n<p><strong>如下写法不得分</strong></p>\n<p>if(flag == TRUE)  ||  if(flag == 1)  ||  if(flag == FLASE)  ||  if(flag == 0)</p>\n<p>**（2）** 请写出 float x 与 “零值” 比较的 if 语句：</p>\n<p>【标准答案】 const float EPSINON = 0.00001; if ((x&gt;= - EPSINON) &amp;&amp; (x &lt;= EPSINON)</p>\n<p>不可将浮点变量用 “==” 或 “！=” 与数字比较，应该设法转化成 “&gt;=” 或 “&lt;=” 此类形式。</p>\n<p><strong>如下写法不得分</strong></p>\n<p>if( x == 0.0)   ||  if(x != 0.0)</p>\n<p><strong>（3）</strong> 请写出 char *p 与 “零值” 比较的 if 语句</p>\n<p>【标准答案】 if (p == NULL)       if (p != NULL)</p>\n<p><strong>如下写法不得分</strong></p>\n<p>if(p == 0)   ||   if(p)</p>\n</blockquote>\n<h3 id=\"sizeof计算\"><a class=\"anchor\" href=\"#sizeof计算\">#</a> sizeof 计算</h3>\n<blockquote>\n<p>以下为 Linux 下的 32 位 C 程序，请计算 sizeof 的值。</p>\n<p>char str[] = “Hello” ; char *p = str ;   int   n = 10;</p>\n<p>请计算</p>\n<p>（1）sizeof (str ) =                     （2）sizeof ( p ) =</p>\n<p>（3） sizeof ( n ) =</p>\n<p>【标准答案】（1）6、（2）4、（3）4</p>\n<p>（4） void Func ( char str[100]){}</p>\n<p>请计算 sizeof (str) =</p>\n<p>（5） void *p = malloc( 100 );</p>\n<p>请计算 sizeof (p) =</p>\n<p>【标准答案】（4）4、（5）4</p>\n</blockquote>\n<h3 id=\"变量定义\"><a class=\"anchor\" href=\"#变量定义\">#</a> 变量定义</h3>\n<blockquote>\n<p>用变量<strong> a</strong> 给出下面的定义</p>\n<p>e)   一个有 10 个指针的数组，该指针是指向一个整型数的；</p>\n<p>f)   一个指向有 10 个整型数数组的指针；</p>\n<p>g)   一个指向函数的指针，该函数有一个整型参数并返回一个整型数；</p>\n<p>h)   一个有 10 个指针的数组，该指针指向一个函数，该函数有一个整型参数并返回一个整型数；</p>\n<p>【标准答案】</p>\n<p>e)int * a[10];</p>\n<p>f)int (*a)[10] *</p>\n<p>*g)int (*a)(int);</p>\n<p>h) int (*a[10])(int)</p>\n</blockquote>\n<h3 id=\"分析代码\"><a class=\"anchor\" href=\"#分析代码\">#</a> 分析代码</h3>\n<blockquote>\n<p><strong>设有以下说明和定义：</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">typedef</span> <span class=\"token keyword\">union</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>   <span class=\"token keyword\">long</span> i<span class=\"token punctuation\">;</span> <span class=\"token keyword\">int</span> k<span class=\"token punctuation\">[</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">char</span> c<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span> DATE<span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">data</span> <span class=\"token punctuation\">&#123;</span> </pre></td></tr><tr><td data-num=\"5\"></td><td><pre>   <span class=\"token keyword\">int</span> cat<span class=\"token punctuation\">;</span> DATE cow<span class=\"token punctuation\">;</span> <span class=\"token keyword\">double</span> dog<span class=\"token punctuation\">;</span>                       </pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span> too<span class=\"token punctuation\">;</span> DATE max<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>则语句 printf (&quot;% d&quot;,sizeof (struct date)+sizeof (max)); 的执行结果是：</p>\n<p>【标准答案】DATE 是一个 union, 变量公用空间。里面最大的变量类型是 int [5], 占用 20 个字节。所以它的大小是 20</p>\n<p>data 是一个 struct, 每个变量分开占用空间。依次为 int4 + DATE20 + double8 = 32.</p>\n<p>所以结果是 20 + 32 = 52.</p>\n<p>当然... 在某些 16 位编辑器下，int 可能是 2 字节，那么结果是 int2 + DATE10 + double8 = 20</p>\n</blockquote>\n<blockquote>\n<p><strong>请问以下代码有什么问题：</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>   <span class=\"token keyword\">char</span> a<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>   <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>str<span class=\"token operator\">=</span><span class=\"token operator\">&amp;</span>a<span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"5\"></td><td><pre>   <span class=\"token function\">strcpy</span><span class=\"token punctuation\">(</span>str<span class=\"token punctuation\">,</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span>str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>   <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>【标准答案】没有为 str 分配内存空间，将会发生异常问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果，但因为越界进行内在读写而导致程序崩溃。</p>\n</blockquote>\n<blockquote>\n<p>请问以下代码有什么问题：</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">char</span><span class=\"token operator\">*</span> s<span class=\"token operator\">=</span><span class=\"token string\">\"AAA\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%s\"</span><span class=\"token punctuation\">,</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>s<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token operator\">=</span><span class=\"token char\">'B'</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%s\"</span><span class=\"token punctuation\">,</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>有什么错？</p>\n<p>【标准答案】&quot;AAA&quot; 是字符串常量。s 是指针，指向这个字符串常量，所以声明 s 的时候就有问题。</p>\n<p>cosnt char* s=&quot;AAA&quot;;</p>\n<p>然后又因为是常量，所以对是 s [0] 的赋值操作是不合法的。</p>\n</blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">getmemory</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>p<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>\tp<span class=\"token operator\">=</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span> <span class=\"token function\">malloc</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token function\">strcpy</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">,</span>“hello world”<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span> <span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>str<span class=\"token operator\">=</span><span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span> <span class=\"token function\">getmemory</span><span class=\"token punctuation\">(</span>str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span>“<span class=\"token operator\">%</span>s<span class=\"token operator\">/</span>n”<span class=\"token punctuation\">,</span>str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> \t\t     <span class=\"token function\">free</span><span class=\"token punctuation\">(</span>str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\">// 会出现什么问题？</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>答案<span class=\"token operator\">:</span> 程序崩溃，getmemory中的malloc 不能返回动态内存， free（）对str操作很危险。</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>\t<span class=\"token keyword\">char</span> aa<span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>     <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span>“<span class=\"token operator\">%</span>d”<span class=\"token punctuation\">,</span><span class=\"token function\">strlen</span><span class=\"token punctuation\">(</span>aa<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token comment\">// 会出现什么问题？打印结果是是多少？</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>【标准答案】<span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>和初不初始化，没有关系，<span class=\"token function\">strlen</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>和初始化有关，打印结果值未知。</pre></td></tr></table></figure><figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">char</span> szstr<span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">strcpy</span><span class=\"token punctuation\">(</span>szstr<span class=\"token punctuation\">,</span><span class=\"token string\">\"0123456789\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">// 产生什么结果？为什么？</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>【标准答案】长度不一样，出现段错误。</pre></td></tr></table></figure><blockquote>\n<p>请简述以下两个 for 循环的优缺点。</p>\n</blockquote>\n<p><img data-src=\"6.jpg\" alt></p>\n<p><img data-src=\"7.jpg\" alt></p>\n<h3 id=\"数组和链表的区别\"><a class=\"anchor\" href=\"#数组和链表的区别\">#</a> 数组和链表的区别</h3>\n<blockquote>\n<p>数组：数据顺序存储，固定大小；</p>\n<p>链表：数据可以随机存储，大小可动态改变</p>\n</blockquote>\n<h3 id=\"解释代码\"><a class=\"anchor\" href=\"#解释代码\">#</a> 解释代码</h3>\n<blockquote>\n<p>int (*s [10])(int) 表示的是什么啊</p>\n<p>【标准答案】int (*s [10])(int) 函数指针数组，每个指针指向一个 int func (int param) 的函数。</p>\n</blockquote>\n<blockquote>\n<p>c 和 c++ 中的 struct 有什么不同？</p>\n<p>【标准答案】c 和 c<ins> 中 struct 的主要区别是 c 中的 struct 不可以含有成员函数，而 c</ins> 中的 struct 可以。c++ 中 struct 和 class 的主要区别在于默认的存取权限不同， struct 默认为 public，而 class 默认为 private</p>\n</blockquote>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>\t<span class=\"token keyword\">int</span> x<span class=\"token operator\">=</span><span class=\"token number\">3</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"4\"></td><td><pre>\t<span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\"</span><span class=\"token punctuation\">,</span>x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"5\"></td><td><pre>\t<span class=\"token keyword\">return</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\">// 问函数既然不会被其它函数调用，为什么要返回 1？</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>【标准答案】mian中，c标准认为<span class=\"token number\">0</span>表示成功，非<span class=\"token number\">0</span>表示错误。具体的值是某中具体出错信息。</pre></td></tr></table></figure></blockquote>\n<h3 id=\"struct计算\"><a class=\"anchor\" href=\"#struct计算\">#</a> struct 计算</h3>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">A</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">char</span> t<span class=\"token operator\">:</span><span class=\"token number\">4</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">char</span> k<span class=\"token operator\">:</span><span class=\"token number\">4</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">short</span> i<span class=\"token operator\">:</span><span class=\"token number\">8</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">long</span> m<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\">// 问 sizeof (A) = ?</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>【标准答案】<span class=\"token number\">8</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">name1</span><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>     <span class=\"token keyword\">char</span> str<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>\t<span class=\"token keyword\">short</span> x<span class=\"token punctuation\">;</span> <span class=\"token keyword\">int</span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token punctuation\">&#125;</span>；</pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token comment\">// 求 sizeof (name1)?</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>【标准答案】<span class=\"token number\">8</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">name2</span><span class=\"token punctuation\">&#123;</span> </pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token keyword\">char</span> str<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token keyword\">int</span> num<span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token keyword\">short</span> x<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token comment\">// 求 sizeof (name2)？</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>【标准答案】<span class=\"token number\">12</span></pre></td></tr></table></figure><h3 id=\"分析指针\"><a class=\"anchor\" href=\"#分析指针\">#</a> 分析 (指针)</h3>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 程序哪里有错误</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">wap</span><span class=\"token punctuation\">(</span> <span class=\"token keyword\">int</span><span class=\"token operator\">*</span> p1<span class=\"token punctuation\">,</span><span class=\"token keyword\">int</span><span class=\"token operator\">*</span> p2 <span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token operator\">*</span>p <span class=\"token operator\">=</span> <span class=\"token operator\">*</span>p1<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token operator\">*</span>p1 <span class=\"token operator\">=</span> <span class=\"token operator\">*</span>p2<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token operator\">*</span>p2 <span class=\"token operator\">=</span> <span class=\"token operator\">*</span>p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>【标准答案】p为野指针</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>ptr 和 <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token comment\">//ptr 的结果是否相同？其中 ptr 为同一个指针。</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>【标准答案】<span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>ptr 和 <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>ptr值是相同的</pre></td></tr></table></figure><h3 id=\"指针\"><a class=\"anchor\" href=\"#指针\">#</a> 指针</h3>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/* 要对绝对地址 0x100000 赋值，我们可以用 (unsigned int*) 0x100000 = 1234;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>那么要是想让程序跳转到绝对地址是 0x100000 去执行，应该怎么做？ */</pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>【标准答案】<span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token number\">0x100000</span> <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span> <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>首先要将<span class=\"token number\">0x100000</span>强制转换成函数指针<span class=\"token punctuation\">,</span>即<span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token number\">0x100000</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>然后再调用它<span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token number\">0x100000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\">/* 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中，要求设置一绝对地址为 0x67a9 的整型变量的值为 0xaa66。编译器是一个纯粹的 ANSI 编译器。写代码去完成这一任务。 */</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>【参考答案】这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换（typecast）为一指针是合法的。这一问题的实现方式随着个人风格不同而不同</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>。典型的类似代码如下：</pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>ptr<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>ptr <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token number\">0x67a9</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token operator\">*</span>ptr <span class=\"token operator\">=</span> <span class=\"token number\">0xaa55</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"内存分析\"><a class=\"anchor\" href=\"#内存分析\">#</a> 内存分析</h3>\n<blockquote>\n<p>堆栈溢出一般是由什么原因导致的？</p>\n<p>【标准答案】没有回收垃圾资源。</p>\n</blockquote>\n<blockquote>\n<p>关于内存的思考题（1）你能看出有什么问题？</p>\n</blockquote>\n<p><img data-src=\"2.jpg\" alt></p>\n<p><img data-src=\"3.jpg\" alt></p>\n<p><img data-src=\"4.jpg\" alt></p>\n<p><img data-src=\"5.jpg\" alt></p>\n<h3 id=\"volatile\"><a class=\"anchor\" href=\"#volatile\">#</a> volatile</h3>\n<blockquote>\n<p><strong>关键字 volatile 有什么含意？并给出三个不同的例子。</strong></p>\n<p>【参考答案】一个定义为 volatile 的变量是说这变量可能会被意想不到地改变，这样，编译器就不会去假设这个变量的值了。精确地说就是，优化器在用到这个变量时必须每次都小心地重新读取这个变量的值，而不是使用保存在寄存器里的备份。下面是 volatile 变量的几个例子：</p>\n<p>1).  并行设备的硬件寄存器（如：状态寄存器）</p>\n<p>2).  一个中断服务子程序中会访问到的非自动变量</p>\n<p>3).  多线程应用中被几个任务共享的变量</p>\n</blockquote>\n<blockquote>\n<p><strong>关键字 volatile 有什么含意？</strong></p>\n<p>【标准答案】提示编译器对象的值可能在编译器未监测到的情况下改变。</p>\n</blockquote>\n<h3 id=\"头文件\"><a class=\"anchor\" href=\"#头文件\">#</a> 头文件</h3>\n<blockquote>\n<p><strong>头文件中的 ifndef/define/endif 干什么用？</strong></p>\n<p>【标准答案】防止该头文件被重复引用。</p>\n</blockquote>\n<blockquote>\n<p><strong>#include &lt;filename.h&gt;  和 #include “filename.h” 有什么区别？</strong></p>\n<p>【标准答案】对于 #include &lt;filename.h&gt; ，编译器从标准库路径开始搜索 filename.h ;</p>\n<p>对于 #include “filename.h” ，编译器从用户的工作路径开始搜索 filename.h 。</p>\n</blockquote>\n<blockquote>\n<p><strong>如何引用一个已经定义过的全局变量？</strong></p>\n<p>【标准答案】可以用引用头文件的方式，也可以用 extern 关键字，如果用引用头文件方式来引用某个在头文件中声明的全局变理，假定你将那个变量写错了</p>\n<p>，那么在编译期间会报错，如果你用 extern 方式引用</p>\n<p>时，假定你犯了同样的错误，那么在编译期间不会报错，而在连接期间报错。</p>\n</blockquote>\n<blockquote>\n<p><strong>全局变量可不可以定义在可被多个.C 文件包含的头文件中？为什么？</strong></p>\n<p>【标准答案】可以，在不同的 C 文件中以 static 形式来声明同名全局变量。可以在不同的 C 文件中声明同名的全局变量，前提是其中只能有一个 C 文件中对此变量赋初值，此时连接不会出错。</p>\n</blockquote>\n<h3 id=\"const-static\"><a class=\"anchor\" href=\"#const-static\">#</a> const &amp; static</h3>\n<blockquote>\n<p><strong>const 有什么用途？（请至少说明两种）</strong></p>\n<p>【标准答案】：</p>\n<p>（1）可以定义 const 常量</p>\n<p>（2）const 可以修饰函数的参数、返回值，甚至函数的定义体。被 const 修饰的东西都受到强制保护，可以预防意外的变动，能提高程序的健壮性。</p>\n</blockquote>\n<blockquote>\n<p><strong>static 有什么用途？（请至少说明两种）</strong></p>\n<p>【标准答案】</p>\n<ol>\n<li>限制变量的作用域（static 全局变量）；</li>\n<li>设置变量的存储域（static 局部变量）。</li>\n</ol>\n</blockquote>\n<blockquote>\n<p><strong>A.c 和 B.c 两个 c 文件中使用了两个相同名字的 static 变量，编译的时候会不会有问题？这两个 static 变量会保存到哪里（栈还是堆或者其他的）?</strong></p>\n<p>【标准答案】static 的全局变量，表明这个变量仅在本模块中有意义，不会影响其他模块。</p>\n<p>他们都放在静态数据区，但是编译器对他们的命名是不同的。</p>\n<p>如果要使变量在其他模块也有意义的话，需要使用 extern 关键字。</p>\n</blockquote>\n<blockquote>\n<p><strong>static 全局变量与普通的全局变量有什么区别？</strong></p>\n<p>【标准答案】 static 全局变量只初使化一次，防止在其他文件单元中被引用；</p>\n<p><strong>static 局部变量和普通局部变量有什么区别</strong></p>\n<p>【标准答案】static 局部变量只被初始化一次，下一次依据上一次结果值；</p>\n<p><strong>static 函数与普通函数有什么区别？</strong></p>\n<p>【标准答案】static 函数在内存中只有一份，普通函数在每个被调用中维持一份拷贝</p>\n</blockquote>\n<h3 id=\"堆栈\"><a class=\"anchor\" href=\"#堆栈\">#</a> 堆栈</h3>\n<blockquote>\n<p><strong>队列和栈有什么区别？</strong></p>\n<p>【标准答案】队列先进先出，栈后进先出。</p>\n</blockquote>\n<blockquote>\n<p><strong>Heap 与 stack 的差别。</strong></p>\n<p>【标准答案】Heap 是堆，stack 是栈。</p>\n<p>Stack 的空间由操作系统自动分配 / 释放，Heap 上的空间手动分配 / 释放。Stack 空间有限，Heap 是很大的自由存储区 C 中的 malloc 函数分配的内存空间即在堆上，C++ 中对应的是 new 操作符。程序在编译期对变量和函数分配内存都在栈上进行，且程序运行过程中函数调用时参数的传递也在栈上进行</p>\n</blockquote>\n<blockquote>\n<p>程序的局部变量存在于<strong>栈 (stack)<strong> 中，全局变量存在于</strong>静态数据区</strong> 中，动态申请数据存在于 ** 堆（ heap）** 中。</p>\n</blockquote>\n<blockquote>\n<p><strong>用两个栈实现一个队列的功能？要求给出算法和思路！</strong></p>\n<p>【参考答案】设 2 个栈为 A,B, 一开始均为空。入队:</p>\n<p>将新元素 push 入栈 A; 出队:</p>\n<p>(1) 判断栈 B 是否为空；</p>\n<p>(2) 如果不为空，则将栈 A 中所有元素依次 pop 出并 push 到栈 B；</p>\n<p>(3) 将栈 B 的栈顶元素 pop 出；</p>\n</blockquote>\n<h3 id=\"宏编译\"><a class=\"anchor\" href=\"#宏编译\">#</a> 宏 &amp; 编译</h3>\n<blockquote>\n<p><strong>用宏定义写出 swap（x，y），即交换两数。</strong></p>\n<p>【标准答案】</p>\n<p>#define swap(x, y) (x)=(x)+(y);(y)=(x)–(y);(x)=(x)–(y);</p>\n</blockquote>\n<blockquote>\n<p><strong>写一个 “标准” 宏，这个宏输入两个参数并返回较小的一个。</strong></p>\n<p>【标准答案】#define Min (X, Y) ((X)&gt;(Y)?(Y):(X))// 结尾没有；</p>\n<p><strong>用预处理指令 #define 声明一个常数，用以表明 1 年中有多少秒（忽略闰年问题）</strong></p>\n<p>【参考答案】#define SECONDS_PER_YEAR (60 * 60* 24 * 365) UL</p>\n</blockquote>\n<blockquote>\n<p><strong>已知一个数组 table，用一个宏定义，求出数据的元素个数。</strong></p>\n<p>【标准答案】</p>\n<p>#define NTBL(table) (sizeof(table)/sizeof(table[0]))</p>\n</blockquote>\n<blockquote>\n<p><strong>什么是预编译，何时需要预编译：</strong></p>\n<p>【标准答案】１、总是使用不经常改动的大型代码体。</p>\n<p>２、程序由多个模块组成，所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下，可以将所有包含文件预编译为一个预编译头。</p>\n</blockquote>\n<blockquote>\n<p><strong>Typedef 在 C 语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如，思考一下下面的例子：</strong></p>\n<p>#define dPS struct s * typedef struct s * tPS;</p>\n<p>以上两种情况的意图都是要定义 dPS 和 tPS 作为一个指向结构 s 指针。哪种方法更好呢？（如果有的话）为什么？</p>\n<p>【参考答案】这是一个非常微妙的问题，任何人答对这个问题（正当的原因）是应当被恭喜的。答案是：typedef 更好。思考下面的例子：</p>\n<p>dPS p1,p2; tPS p3,p4;</p>\n<p>第一个扩展为</p>\n<p>struct s * p1, p2;</p>\n<p>上面的代码定义 p1 为一个指向结构的指，p2 为一个实际的结构，这也许不是你想要的。第二个例子正确地定义了 p3 和 p4 两个指针。</p>\n</blockquote>\n<h3 id=\"extern-c\"><a class=\"anchor\" href=\"#extern-c\">#</a> extern “C”</h3>\n<blockquote>\n<p><strong>在 C++ 程序中调用被 C 编译器编译后的函数， 为什么要加 extern “C”？</strong></p>\n<p>【标准答案】C<ins> 语言支持函数重载，C 语言不支持函数重载。函数被 C</ins> 编译后在库中的名字与 C 语言的不同。假设某个函数的原型为： void foo (int x, int y); 该函数被 C 编译器编译后在库中的名字为_foo，而 C<ins> 编译器则会产生像_foo_int_int 之类的名字。 C</ins> 提供了 C 连接交换指定符号 extern “C” 来解决名字匹配问题。</p>\n</blockquote>\n<h3 id=\"代码分析2\"><a class=\"anchor\" href=\"#代码分析2\">#</a> 代码分析 2</h3>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 1. 请写出下列代码的输出内容 #include &lt;stdio.h></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">int</span> a<span class=\"token punctuation\">,</span>b<span class=\"token punctuation\">,</span>c<span class=\"token punctuation\">,</span>d<span class=\"token punctuation\">;</span> a<span class=\"token operator\">=</span><span class=\"token number\">10</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    b<span class=\"token operator\">=</span>a<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span> c<span class=\"token operator\">=</span><span class=\"token operator\">++</span>a<span class=\"token punctuation\">;</span> d<span class=\"token operator\">=</span><span class=\"token number\">10</span><span class=\"token operator\">*</span>a<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"b，c，d：%d，%d，%d\"</span>，b，c，d）<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>【标准答案】<span class=\"token number\">10</span>，<span class=\"token number\">12</span>，<span class=\"token number\">120</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>           </pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>p1<span class=\"token punctuation\">;</span> <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">long</span> <span class=\"token operator\">*</span>p2<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>p1<span class=\"token operator\">=</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token number\">0x801000</span><span class=\"token punctuation\">;</span> p2<span class=\"token operator\">=</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">long</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token number\">0x810000</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token comment\">// 2. 请问 p1+5= ;   p2+5= ;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>【标准答案】<span class=\"token number\">0x801005</span>、<span class=\"token number\">0x810020</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>           </pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">int</span> a<span class=\"token punctuation\">[</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token operator\">=</span><span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>ptr<span class=\"token operator\">=</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>a<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span>“<span class=\"token operator\">%</span>d，<span class=\"token operator\">%</span>d”<span class=\"token punctuation\">,</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span>a<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span>ptr<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token comment\">// 3. 请问输出：</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>【标准答案】<span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>      </pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token comment\">// 4. 以下是求一个数的平方的程序，请找出错误: #define SQUARE (a)((a)*(a))</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token keyword\">int</span> a<span class=\"token operator\">=</span><span class=\"token number\">5</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">int</span> b<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>b<span class=\"token operator\">=</span><span class=\"token function\">SQUARE</span><span class=\"token punctuation\">(</span>a<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>【标准答案】宏在预编译时会以替换的形式展开，仅仅会替换。涉及到宏的地方，不要用<span class=\"token operator\">++</span> <span class=\"token operator\">--</span>，标准中对此没有规定，因此最终结果将会依赖于不同的编译器。执行程序的答案可能是<span class=\"token number\">25</span>、也有可能是<span class=\"token number\">36</span>。</pre></td></tr><tr><td data-num=\"29\"></td><td><pre>           </pre></td></tr><tr><td data-num=\"30\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">Max_CB</span> <span class=\"token expression\"><span class=\"token number\">500</span></span></span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">LmiQueryCSmd</span><span class=\"token punctuation\">(</span>Struct MSgCB <span class=\"token operator\">*</span> pmsg<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">char</span> ucCmdNum<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>    <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>    <span class=\"token keyword\">for</span><span class=\"token punctuation\">(</span>ucCmdNum<span class=\"token operator\">=</span><span class=\"token number\">0</span><span class=\"token punctuation\">;</span>ucCmdNum<span class=\"token operator\">&lt;</span>Max_CB<span class=\"token punctuation\">;</span>ucCmdN um<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>    <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>        <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre><span class=\"token comment\">// 5. 这段代码执行有什么问题？</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>【标准答案】死循环</pre></td></tr><tr><td data-num=\"42\"></td><td><pre><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">char</span> <span class=\"token comment\">// 无符号字符型 表示范围 0~255 char // 有符号字符型 表示范围 - 128~127</span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre></pre></td></tr><tr><td data-num=\"44\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">modifyvalue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"45\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"46\"></td><td><pre>    <span class=\"token keyword\">return</span><span class=\"token punctuation\">(</span>x<span class=\"token operator\">+=</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"47\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">changevalue</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> x<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"49\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"50\"></td><td><pre>    <span class=\"token keyword\">return</span><span class=\"token punctuation\">(</span>x<span class=\"token operator\">+=</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"51\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"53\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"54\"></td><td><pre>    <span class=\"token keyword\">int</span> x<span class=\"token operator\">=</span><span class=\"token number\">10</span><span class=\"token punctuation\">;</span> x<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"55\"></td><td><pre>    <span class=\"token function\">changevalue</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> x<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"56\"></td><td><pre>    <span class=\"token function\">modifyvalue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"57\"></td><td><pre>    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"First output:%dn\"</span><span class=\"token punctuation\">,</span>x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> x<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"58\"></td><td><pre>    <span class=\"token function\">changevalue</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Second output:%dn\"</span><span class=\"token punctuation\">,</span>x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token function\">modifyvalue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"59\"></td><td><pre>    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Third output:%dn\"</span><span class=\"token punctuation\">,</span>x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"60\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"61\"></td><td><pre><span class=\"token comment\">// 6. 输出？</span></pre></td></tr><tr><td data-num=\"62\"></td><td><pre>【 标准答案】<span class=\"token number\">12</span>、<span class=\"token number\">13</span>、<span class=\"token number\">13</span></pre></td></tr><tr><td data-num=\"63\"></td><td><pre></pre></td></tr><tr><td data-num=\"64\"></td><td><pre><span class=\"token comment\">// 7. 请写出下列代码的输出内容</span></pre></td></tr><tr><td data-num=\"65\"></td><td><pre>＃include<span class=\"token operator\">&lt;</span>stdio<span class=\"token punctuation\">.</span>h<span class=\"token operator\">></span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"66\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"67\"></td><td><pre>    <span class=\"token keyword\">int</span> a<span class=\"token punctuation\">,</span>b<span class=\"token punctuation\">,</span>c<span class=\"token punctuation\">,</span>d<span class=\"token punctuation\">;</span> a<span class=\"token operator\">=</span><span class=\"token number\">10</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"68\"></td><td><pre>    b<span class=\"token operator\">=</span>a<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span> c<span class=\"token operator\">=</span><span class=\"token operator\">++</span>a<span class=\"token punctuation\">;</span> d<span class=\"token operator\">=</span><span class=\"token number\">10</span><span class=\"token operator\">*</span>a<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"69\"></td><td><pre>    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"b，c，d：%d，%d，%d\"</span>，b，c，d）<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"70\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"71\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"72\"></td><td><pre>【标准答案】<span class=\"token number\">10</span>，<span class=\"token number\">12</span>，<span class=\"token number\">120</span></pre></td></tr></table></figure><blockquote>\n<ol start=\"8\">\n<li>找出程序的错误</li>\n</ol>\n</blockquote>\n<p><img data-src=\"8.jpg\" alt></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 9. 下面的代码输出是什么，为什么？ </span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">foo</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span> <span class=\"token number\">6</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">int</span> b <span class=\"token operator\">=</span> <span class=\"token operator\">-</span><span class=\"token number\">20</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">(</span>a<span class=\"token operator\">+</span>b <span class=\"token operator\">></span> <span class=\"token number\">6</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span> <span class=\"token function\">puts</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"> 6\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> <span class=\"token function\">puts</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&lt;= 6\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>【参考答案】这个问题测试你是否懂得C语言中的整数自动转换原则，</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>我发现有些开发者懂得极少这些东西。不管如何，这无符号整型问题的答案是输出是“<span class=\"token operator\">></span><span class=\"token number\">6</span>”。原因是当表达式中存在有符号类型和无符号类型时所有的数都自动转换为无符号类型。因此<span class=\"token operator\">-</span><span class=\"token number\">20</span>变成了一个非常大的正整数，所以该表达式计算出的结果大于<span class=\"token number\">6</span>。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题，你也就到了得不到这份工作的边缘。</pre></td></tr></table></figure><h3 id=\"other\"><a class=\"anchor\" href=\"#other\">#</a> other</h3>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 1. 一语句实现 x 是否为 2 的若干次幂的判断。</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">int</span> a<span class=\"token punctuation\">;</span> <span class=\"token function\">scanf</span><span class=\"token punctuation\">(</span>“<span class=\"token operator\">%</span>d”<span class=\"token punctuation\">,</span><span class=\"token operator\">&amp;</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span>“<span class=\"token operator\">%</span>c”<span class=\"token punctuation\">,</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span><span class=\"token operator\">&amp;</span><span class=\"token punctuation\">(</span>a<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token operator\">?</span>’n’<span class=\"token operator\">:</span>’y’<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//  若是打印 y，否则 n</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\">// 2. 中断是嵌入式系统中重要的组成部分，这导致了很多编译开发商提供一种扩展 — 让标准 C 支持中断。具代表事实是，产生了一个新的关键字 interrupt。下面的代码就使用了\tinterrupt 关键字去定义了一个中断服务子程序 (ISR)，请评论一下这段代码的。</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>interrupt <span class=\"token keyword\">double</span> <span class=\"token function\">compute_area</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">double</span> radius<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">double</span> area <span class=\"token operator\">=</span> PI <span class=\"token operator\">*</span> radius <span class=\"token operator\">*</span> radius<span class=\"token punctuation\">;</span> <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\" Area = %f\"</span><span class=\"token punctuation\">,</span> area<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token keyword\">return</span> area<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>【参考答案】这个函数有太多的错误了，以至让人不知从何说起了：</pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>\tISR 不能返回一个值。如果你不懂这个，那么你不会被雇用的。</pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>\tISR 不能传递参数。如果你没有看到这一点，你被雇用的机会等同第一项。</pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token number\">3</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>\t在许多的处理器<span class=\"token operator\">/</span>编译器中，浮点一般都是不可重入的。有些处理器<span class=\"token operator\">/</span>编译器需要让额处的寄存器入栈，有些处理器<span class=\"token operator\">/</span>编译器就是不允许在ISR中做浮点运算。此外，ISR应该是短而有效率的，在ISR中做浮点运算是不明智的。</pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>\t与第三点一脉相承，<span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>经常有重入和性能上的问题。如果你丢掉</pre></td></tr><tr><td data-num=\"19\"></td><td><pre>了第三和第四点，我不会太为难你的。不用说，如果你能得到后两点，那么你的被雇用前景越来越光明了</pre></td></tr></table></figure><h3 id=\"代码编写\"><a class=\"anchor\" href=\"#代码编写\">#</a> 代码编写</h3>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 1. 编写 strcpy 函数，已知 strcpy 函数的原型是 char *strcpy (char *strDest, const char *strSrc); 其中 strDest 是目的字符串， strSrc 是源字符串。</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>（<span class=\"token number\">1</span>）\t不调用 C<span class=\"token operator\">++</span><span class=\"token operator\">/</span>C 的字符串库函数，请编写函数</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>strcpy 。</pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>（<span class=\"token number\">2</span>）\tstrcpy 能把 strSrc 的内容复制到 strDest，为什么还要 <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span> 类型的返回值？</pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\">// 2. 请编写一个 C 函数，该函数给出一个字节中被置 1 的位的个数。</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span> <span class=\"token function\">TestAsOne0</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">char</span> log<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">int</span> i<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span> num<span class=\"token operator\">=</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> val<span class=\"token punctuation\">;</span> <span class=\"token keyword\">for</span><span class=\"token punctuation\">(</span>i<span class=\"token operator\">=</span><span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">&lt;</span><span class=\"token number\">8</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        val <span class=\"token operator\">=</span> log <span class=\"token operator\">>></span> i<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 移位 val &amp;= 0x01; // 与 1 相与 if (val)</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        num<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">return</span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token comment\">// 3. 实现 strcmp 函数</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre></pre></td></tr><tr><td data-num=\"21\"></td><td><pre></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token comment\">// 4. 华为面试题：怎么判断链表中是否有环？</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>【参考答案】答：用两个指针来遍历这个单向链表，第一个指针p1，每次走一步；第二个指针p2，每次走两步； 当p2 指针追上 p1的时候，就表明链表当中有环路了。</pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token keyword\">int</span>\t<span class=\"token function\">testLinkRing</span><span class=\"token punctuation\">(</span>Link <span class=\"token operator\">*</span>head<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    Link <span class=\"token operator\">*</span>t1<span class=\"token operator\">=</span>head<span class=\"token punctuation\">,</span><span class=\"token operator\">*</span>t2<span class=\"token operator\">=</span>head<span class=\"token punctuation\">;</span> <span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span> t1<span class=\"token operator\">-></span>next <span class=\"token operator\">&amp;&amp;</span> t2<span class=\"token operator\">-></span>next<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>    <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>        t1 <span class=\"token operator\">=</span> t1<span class=\"token operator\">-></span>next<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token constant\">NULL</span> <span class=\"token operator\">==</span> <span class=\"token punctuation\">(</span>t2 <span class=\"token operator\">=</span> t2<span class=\"token operator\">-></span>next<span class=\"token operator\">-></span>next<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\t<span class=\"token comment\">// 无环</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>t1 <span class=\"token operator\">==</span> t2<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre></pre></td></tr><tr><td data-num=\"36\"></td><td><pre><span class=\"token comment\">// 5. 实现双向链表删除一个节点 P，在节点 P 后插入一个节点，写出这两个函数。</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre></pre></td></tr><tr><td data-num=\"38\"></td><td><pre></pre></td></tr><tr><td data-num=\"39\"></td><td><pre><span class=\"token comment\">// 6. 把一个链表反向 。</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre>【参考答案】从第一个元素开始，ps指向他，将他（ps）指向头节点<span class=\"token punctuation\">(</span>ps<span class=\"token operator\">-></span>next<span class=\"token operator\">=</span> head<span class=\"token punctuation\">)</span>，将ps设为头节点（head <span class=\"token operator\">=</span> ps<span class=\"token punctuation\">;</span>）操作下一个元素（ps <span class=\"token operator\">=</span> pe<span class=\"token operator\">-></span>next<span class=\"token punctuation\">;</span>）等于是依次将每个元素翻到原头节点前面。</pre></td></tr><tr><td data-num=\"41\"></td><td><pre></pre></td></tr><tr><td data-num=\"42\"></td><td><pre><span class=\"token comment\">// 7. 取一个整数 a 从右端开始的 4～7 位。</span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"44\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"45\"></td><td><pre>\t<span class=\"token keyword\">unsigned</span> a<span class=\"token punctuation\">,</span>b<span class=\"token punctuation\">,</span>c<span class=\"token punctuation\">,</span>d<span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"46\"></td><td><pre>    <span class=\"token function\">scanf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%o\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">&amp;</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"47\"></td><td><pre>    b<span class=\"token operator\">=</span>a<span class=\"token operator\">>></span><span class=\"token number\">4</span><span class=\"token punctuation\">;</span> c<span class=\"token operator\">=</span><span class=\"token operator\">~</span><span class=\"token punctuation\">(</span><span class=\"token operator\">~</span><span class=\"token number\">0</span><span class=\"token operator\">&lt;&lt;</span><span class=\"token number\">4</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre>\td<span class=\"token operator\">=</span>b<span class=\"token operator\">&amp;</span>c<span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"49\"></td><td><pre>    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%o\\n%o\\n\"</span><span class=\"token punctuation\">,</span>a<span class=\"token punctuation\">,</span>d<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"50\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure>",
            "tags": [
                "嵌入式面试八股文",
                "嵌入式面试八股文"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2024/03/19/baguwen/0-1-%E5%B5%8C%E8%BD%AF%E7%AC%94%E8%AF%95%E9%9D%A2%E8%AF%95/",
            "url": "https://littlestory1.github.io/2024/03/19/baguwen/0-1-%E5%B5%8C%E8%BD%AF%E7%AC%94%E8%AF%95%E9%9D%A2%E8%AF%95/",
            "title": "嵌入式软件笔试面试八股文",
            "date_published": "2024-03-18T17:09:00.000Z",
            "content_html": "<p><img data-src=\"1.jpg\" alt></p>\n<h2 id=\"嵌入式软件笔试面试\"><a class=\"anchor\" href=\"#嵌入式软件笔试面试\">#</a> 嵌入式软件笔试面试</h2>\n<h3 id=\"define-声明\"><a class=\"anchor\" href=\"#define-声明\">#</a> #define 声明</h3>\n<blockquote>\n<p>用预处理指令 #define 声明一个常数，用以表明 1 年中有多少秒（忽略闰年问题）<br>\n答案： #define SECONDS_PER_YEAR (60 * 60 * 24 * 365) UL<br>\n<strong> 我在这想看到几件事情：</strong></p>\n<ol>\n<li>#define 语法的基本知识（例如：不能以分号结束，括号的使用，等等）</li>\n<li>懂得预处理器将为你计算常数表达式的值，因此，直接写出你是如何计算一年中有多少秒而不是计算出实际的值，是更清晰而没有代价的。</li>\n<li>意识到这个表达式将使一个 16 位机的整型数溢出 - 因此要用到长整型符号 L, 告诉编译器这个常数是的长整型数。</li>\n<li>如果你在你的表达式中用到 UL（表示无符号长整型），那么你有了一个好的起点。记住，第一印象很重要。</li>\n</ol>\n</blockquote>\n<h3 id=\"标准宏min\"><a class=\"anchor\" href=\"#标准宏min\">#</a> &quot;标准&quot; 宏 MIN</h3>\n<blockquote>\n<p>写一个 &quot;标准&quot; 宏 MIN ，这个宏输入两个参数并返回较小的一个。<br>\n答案： #define MIN (A,B) （（A） &lt;= (B) ? (A) : (B))<br>\n<strong> 这个测试是为下面的目的而设的：</strong></p>\n<ol>\n<li>标识 #define 在宏中应用的基本知识。这是很重要的。因为在 嵌入 (inline) 操作符 变为标准 C 的一部分之前，宏是方便产生嵌入代码的唯一方法，对于嵌入式系统来说，为了能达到要求的性能，嵌入代码经常是必须的方法。</li>\n<li>三重条件操作符的知识。这个操作符存在 C 语言中的原因是它使得编译器能产生比 if-then-else 更优化的代码，了解这个用法是很重要的。</li>\n<li>懂得在宏中小心地把参数用括号括起来</li>\n<li>我也用这个问题开始讨论宏的副作用，例如：当你写下面的代码时会发生什么事？<br>\nleast = MIN(*p++, b)；</li>\n</ol>\n</blockquote>\n<h3 id=\"死循环\"><a class=\"anchor\" href=\"#死循环\">#</a> 死循环</h3>\n<blockquote>\n<p>嵌入式系统中经常要用到无限循环，你怎么样用 C 编写死循环呢？<br>\n这个问题用几个解决方案。我首选的方案是：</p>\n<p>while(1)<br>\n{}</p>\n<p>一些程序员更喜欢如下方案：</p>\n<p>for(;😉<br>\n{}</p>\n<p>这个实现方式让我为难，因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案，我将用这个作为一个机会去探究他们这样做的基本原理。如果他们的基本答案是：&quot;我被教着这样做，但从没有想到过为什么。&quot; 这会给我留下一个坏印象。</p>\n<p>第三个方案是用 goto<br>\nLoop:<br>\n...<br>\ngoto Loop;<br>\n 应试者如给出上面的方案，这说明或者他是一个汇编语言程序员（这也许是好事）或者他是一个想进入新领域的 BASIC/FORTRAN 程序员。</p>\n</blockquote>\n<h3 id=\"数据声明\"><a class=\"anchor\" href=\"#数据声明\">#</a> 数据声明</h3>\n<blockquote>\n<p>a) 一个整型数（An integer）<br>\nb) 一个指向整型数的指针（ A pointer to an integer）<br>\nc) 一个指向指针的的指针，它指向的指针是指向一个整型数（ A pointer to a pointer to an intege）r<br>\nd) 一个有 10 个整型数的数组（ An array of 10 integers）<br>\ne) 一个有 10 个指针的数组，该指针是指向一个整型数的。（An array of 10 pointers to integers）<br>\nf) 一个指向有 10 个整型数数组的指针（ A pointer to an array of 10 integers）<br>\ng) 一个指向函数的指针，该函数有一个整型参数并返回一个整型数（A pointer to a function that takes an integer as an argument and returns an integer）<br>\nh) 一个有 10 个指针的数组，该指针指向一个函数，该函数有一个整型参数并返回一个整型数（ An array of ten pointers to functions that take an integer argument and return an integer ）</p>\n<p>答案是：<br>\na) int a; // An integer<br>\nb) int *a; // A pointer to an integer<br>\nc) int **a; // A pointer to a pointer to an integer<br>\nd) int a[10]; // An array of 10 integers<br>\ne) int *a[10]; // An array of 10 pointers to integers<br>\nf) int (*a)[10]; // A pointer to an array of 10 integers<br>\ng) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer<br>\nh) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer</p>\n</blockquote>\n<h3 id=\"static的作用\"><a class=\"anchor\" href=\"#static的作用\">#</a> static 的作用</h3>\n<blockquote>\n<ol>\n<li>在函数体，一个被声明为静态的变量在这一函数被调用过程中维持其值不变。</li>\n<li>在模块内（但在函数体外），一个被声明为静态的变量可以被模块内所用函数访问，但不能被模块外其它函数访问。它是一个本地的全局变量。</li>\n<li>在模块内，一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是，这个函数被限制在声明它的模块的本地范围内使用。</li>\n</ol>\n</blockquote>\n<h3 id=\"const含意\"><a class=\"anchor\" href=\"#const含意\">#</a> const 含意</h3>\n<blockquote>\n<p>我只要一听到被面试者说：&quot;const 意味着常数&quot;，我就知道我正在和一个业余者打交道。去年 Dan Saks 已经在他的文章里完全概括了 const 的所有用法，因此 ESP (译者：Embedded Systems Programming) 的每一位读者应该非常熟悉 const 能做什么和不能做什么。如果你从没有读到那篇文章，只要能说出 const 意味着 &quot;只读&quot; 就可以了。尽管这个答案不是完全的答案，但我接受它作为一个正确的答案。（如果你想知道更详细的答案，仔细读一下 Saks 的文章吧。）<br>\n如果应试者能正确回答这个问题，我将问他一个附加的问题：<br>\n下面的声明都是什么意思？</p>\n<p>const int a;<br>\nint const a;<br>\nconst int *a;<br>\nint * const a;<br>\nint const * a const;</p>\n<p>前两个的作用是一样，a 是一个常整型数。第三个意味着 a 是一个指向常整型数的指针（也就是，整型数是不可修改的，但指针可以）。第四个意思 a 是一个指向整型数的常指针（也就是说，指针指向的整型数是可以修改的，但指针是不可修改的）。最后一个意味着 a 是一个指向常整型数的常指针（也就是说，指针指向的整型数是不可修改的，同时指针也是不可修改的）。如果应试者能正确回答这些问题，那么他就给我留下了一个好印象。顺带提一句，也许你可能会问，即使不用关键字 const，也还是能很容易写出功能正确的程序，那么我为什么还要如此看重关键字 const 呢？</p>\n<p>我也如下的几下理由：</p>\n<ol>\n<li>关键字 const 的作用是为给读你代码的人传达非常有用的信息，实际上，声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾，你就会很快学会感谢这点多余的信息。（当然，懂得用 const 的程序员很少会留下的垃圾让别人来清理的。）</li>\n<li>通过给优化器一些附加的信息，使用关键字 const 也许能产生更紧凑的代码。</li>\n<li>合理地使用关键字 const 可以使编译器很自然地保护那些不希望被改变的参数，防止其被无意的代码修改。简而言之，这样可以减少 bug 的出现。</li>\n</ol>\n</blockquote>\n<h3 id=\"volatile含意\"><a class=\"anchor\" href=\"#volatile含意\">#</a> volatile 含意</h3>\n<blockquote>\n<p>一个定义为 volatile 的变量是说这变量可能会被意想不到地改变，这样，编译器就不会去假设这个变量的值了。精确地说就是，优化器在用到这个变量时必须每次都小心地重新读取这个变量的值，而不是使用保存在寄存器里的备份。下面是 volatile 变量的几个例子：</p>\n<ol>\n<li>并行设备的硬件寄存器（如：状态寄存器）</li>\n<li>一个中断服务子程序中会访问到的非自动变量 (Non-automatic variables)</li>\n<li>多线程应用中被几个任务共享的变量</li>\n</ol>\n<p>回答不出这个问题的人是不会被雇佣的。我认为这是区分 C 程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS 等等打交道，所有这些都要求用到 volatile 变量。不懂得 volatile 的内容将会带来灾难。<br>\n假设被面试者正确地回答了这是问题（嗯，怀疑是否会是这样），我将稍微深究一下，看一下这家伙是不是直正懂得 volatile 完全的重要性。<br>\n1) 一个参数既可以是 const 还可以是 volatile 吗？解释为什么。<br>\n2); 一个指针可以是 volatile 吗？解释为什么。<br>\n3); 下面的函数有什么错误：</p>\n<p>int square(volatile int *ptr)<br>\n{<br>\nreturn *ptr * *ptr;<br>\n}</p>\n<p><strong>下面是答案：</strong><br>\n1) 是的。一个例子是只读的状态寄存器。它是 volatile 因为它可能被意想不到地改变。它是 const 因为程序不应该试图去修改它。<br>\n2); 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个 buffer 的指针时。<br>\n\\3) 这段代码有点变态。这段代码的目的是用来返指针<em> ptr 指向值的平方，但是，由于</em> ptr 指向一个 volatile 型参数，编译器将产生类似下面的代码：</p>\n<p>int square(volatile int *ptr)<br>\n{<br>\nint a,b;<br>\na = *ptr;<br>\nb = *ptr;<br>\nreturn a * b;<br>\n}</p>\n<p>由于 * ptr 的值可能被意想不到地该变，因此 a 和 b 可能是不同的。结果，这段代码可能返不是你所期望的平方值！正确的代码如下：</p>\n<p>long square(volatile int *ptr)<br>\n{<br>\nint a;<br>\na = *ptr;<br>\nreturn a * a;<br>\n}</p>\n</blockquote>\n<h3 id=\"位操作\"><a class=\"anchor\" href=\"#位操作\">#</a> 位操作</h3>\n<blockquote>\n<p>嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量 a，写两段代码，第一个设置 a 的 bit 3，第二个清除 a 的 bit 3。在以上两个操作中，要保持其它位不变。<br>\n对这个问题有三种基本的反应</p>\n<ol>\n<li>不知道如何下手。该被面者从没做过任何嵌入式系统的工作。</li>\n<li>用 bit fields。Bit fields 是被扔到 C 语言死角的东西，它保证你的代码在不同编译器之间是不可移植的，同时也保证了的你的代码是不可重用的。我最近不幸看到 Infineon 为其较复杂的通信芯片写的驱动程序，它用到了 bit fields 因此完全对我无用，因为我的编译器用其它的方式来实现 bit fields 的。从道德讲：永远不要让一个非嵌入式的家伙粘实际硬件的边。</li>\n<li>用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法，是应该被用到的方法。</li>\n</ol>\n<p><strong>最佳的解决方案如下：</strong></p>\n<p>#define BIT3 (0x1 &lt;&lt; 3)<br>\nstatic int a;</p>\n<p>void set_bit3(void)<br>\n{<br>\na |= BIT3;<br>\n}<br>\nvoid clear_bit3(void)<br>\n{<br>\na &amp;= ~BIT3;<br>\n}</p>\n<p>一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数，这也是可以接受的。我希望看到几个要点：说明常数、|= 和 &amp;=~ 操作。</p>\n</blockquote>\n<h3 id=\"访问固定的内存位置\"><a class=\"anchor\" href=\"#访问固定的内存位置\">#</a> 访问固定的内存位置</h3>\n<blockquote>\n<p>嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中，要求设置一绝对地址为 0x67a9 的整型变量的值为 0xaa66。编译器是一个纯粹的 ANSI 编译器。写代码去完成这一任务。<br>\n这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换（typecast）为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下：<br>\nint *ptr;<br>\nptr = (int *)0x67a9;<br>\n*ptr = 0xaa55;</p>\n<p>A more obscure approach is:<br>\n 一个较晦涩的方法是：</p>\n<p>*(int * const)(0x67a9) = 0xaa55;</p>\n<p>即使你的品味更接近第二种方案，但我建议你在面试时使用第一种方案。</p>\n</blockquote>\n<h3 id=\"中断\"><a class=\"anchor\" href=\"#中断\">#</a> 中断</h3>\n<blockquote>\n<p>中断是嵌入式系统中重要的组成部分，这导致了很多编译开发商提供一种扩展 — 让标准 C 支持中断。具代表事实是，产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt 关键字去定义了一个中断服务子程序 (ISR)，请评论一下这段代码的。</p>\n<p>__interrupt double compute_area (double radius)<br>\n{<br>\ndouble area = PI * radius * radius;<br>\nprintf(&quot;\\nArea = %f&quot;, area);<br>\nreturn area;<br>\n}</p>\n<p>这个函数有太多的错误了，以至让人不知从何说起了：</p>\n<ol>\n<li>ISR 不能返回一个值。如果你不懂这个，那么你不会被雇用的。</li>\n<li>ISR 不能传递参数。如果你没有看到这一点，你被雇用的机会等同第一项。</li>\n<li>在许多的处理器 / 编译器中，浮点一般都是不可重入的。有些处理器 / 编译器需要让额处的寄存器入栈，有些处理器 / 编译器就是不允许在 ISR 中做浮点运算。此外，ISR 应该是短而有效率的，在 ISR 中做浮点运算是不明智的。</li>\n<li>与第三点一脉相承，printf () 经常有重入和性能上的问题。如果你丢掉了第三和第四点，我不会太为难你的。不用说，如果你能得到后两点，那么你的被雇用前景越来越光明了。</li>\n</ol>\n</blockquote>\n<h3 id=\"代码分析\"><a class=\"anchor\" href=\"#代码分析\">#</a> 代码分析</h3>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">foo</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span> <span class=\"token number\">6</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">int</span> b <span class=\"token operator\">=</span> <span class=\"token operator\">-</span><span class=\"token number\">20</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">(</span>a<span class=\"token operator\">+</span>b <span class=\"token operator\">></span> <span class=\"token number\">6</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> <span class=\"token function\">puts</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"> 6\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> <span class=\"token function\">puts</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"&lt;= 6\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><blockquote>\n<p>这个问题测试你是否懂得 C 语言中的整数自动转换原则，我发现有些开发者懂得极少这些东西。不管如何，这无符号整型问题的答案是输出是 &quot;&gt;6&quot;。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此 - 20 变成了一个非常大的正整数，所以该表达式计算出的结果大于 6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题，你也就到了得不到这份工作的边缘。</p>\n</blockquote>\n<h3 id=\"评价代码\"><a class=\"anchor\" href=\"#评价代码\">#</a> 评价代码</h3>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span> zero <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span> compzero <span class=\"token operator\">=</span> <span class=\"token number\">0xFFFF</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">/*1's complement of zero */</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\">// 对于一个 int 型不是 16 位的处理器为说，上面的代码是不正确的。应编写如下：</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span> compzero <span class=\"token operator\">=</span> <span class=\"token operator\">~</span><span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><blockquote>\n<p>这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里，好的嵌入式程序员非常准确地明白硬件的细节和它的局限，然而 PC 机程序往往把硬件作为一个无法避免的烦恼。<br>\n到了这个阶段，应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很好，那么这个测试就在这里结束了。但如果显然应试者做得不错，那么我就扔出下面的追加问题，这些问题是比较难的，我想仅仅非常优秀的应试者能做得不错。提出这些问题，我希望更多看到应试者应付问题的方法，而不是答案。不管如何，你就当是这个娱乐吧...</p>\n</blockquote>\n<h3 id=\"动态内存分配\"><a class=\"anchor\" href=\"#动态内存分配\">#</a> 动态内存分配</h3>\n<blockquote>\n<p>尽管不像非嵌入式计算机那么常见，嵌入式系统还是有从堆（heap）中动态分配内存的过程的。那么嵌入式系统中，动态分配内存可能发生的问题是什么？<br>\n这里，我期望应试者能提到内存碎片，碎片收集的问题，变量的持行时间等等。这个主题已经在 ESP 杂志中被广泛地讨论过了（主要是 P.J. Plauger, 他的解释远远超过我这里能提到的任何解释），所有回过头看一下这些杂志吧！让应试者进入一种虚假的安全感觉后，我拿出这么一个小节目：<br>\n下面的代码片段的输出是什么，为什么？</p>\n</blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>ptr<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>ptr <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token function\">malloc</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span> </pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token function\">puts</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Got a null pointer\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">else</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token function\">puts</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Got a valid pointer\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><blockquote>\n<p>这是一个有趣的问题。最近在我的一个同事不经意把 0 值传给了函数 malloc，得到了一个合法的指针之后，我才想到这个问题。这就是上面的代码，该代码的输出是 &quot;Got a valid pointer&quot;。我用这个来开始讨论这样的一问题，看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要，但解决问题的方法和你做决定的基本原理更重要些。</p>\n</blockquote>\n<h3 id=\"typedef\"><a class=\"anchor\" href=\"#typedef\">#</a> Typedef</h3>\n<blockquote>\n<p>Typedef 在 C 语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如，思考一下下面的例子：</p>\n<p>#define dPS struct s *<br>\ntypedef struct s * tPS;</p>\n<p>以上两种情况的意图都是要定义 dPS 和 tPS 作为一个指向结构 s 指针。哪种方法更好呢？（如果有的话）为什么？<br>\n这是一个非常微妙的问题，任何人答对这个问题（正当的原因）是应当被恭喜的。答案是：typedef 更好。思考下面的例子：</p>\n<p>dPS p1,p2;<br>\ntPS p3,p4;</p>\n<p>第一个扩展为</p>\n<p>struct s * p1, p2;</p>\n<p>上面的代码定义 p1 为一个指向结构的指，p2 为一个实际的结构，这也许不是你想要的。第二个例子正确地定义了 p3 和 p4 两个指针。</p>\n</blockquote>\n<h3 id=\"晦涩的语法\"><a class=\"anchor\" href=\"#晦涩的语法\">#</a> 晦涩的语法</h3>\n<blockquote>\n<p>C 语言同意一些令人震惊的结构，下面的结构是合法的吗，如果是它做些什么？</p>\n<p>int a = 5, b = 7, c;<br>\nc = a+++b;</p>\n<p>这个问题将做为这个测验的一个愉快的结尾。不管你相不相信，上面的例子是完全合乎语法的。问题是编译器如何处理它？水平不高的编译作者实际上会争论这个问题，根据最处理原则，编译器应当能处理尽可能所有合法的用法。因此，上面的代码被处理成：</p>\n<p>c = a++ + b;</p>\n<p>因此，这段代码持行后 a = 6, b = 7, c = 12。<br>\n如果你知道答案，或猜出正确答案，做得好。如果你不知道答案，我也不把这个当作问题。我发现这个问题的最大好处是这是一个关于代码编写风格，代码的可读性，代码的可修改性的好的话题。</p>\n</blockquote>\n",
            "tags": [
                "嵌入式面试八股文",
                "嵌入式面试八股文"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2024/03/19/baguwen/1-0-C%E8%AF%AD%E8%A8%80-%E6%9D%82%E9%A1%B9/",
            "url": "https://littlestory1.github.io/2024/03/19/baguwen/1-0-C%E8%AF%AD%E8%A8%80-%E6%9D%82%E9%A1%B9/",
            "title": "1-0-C语言-杂项",
            "date_published": "2024-03-18T17:09:00.000Z",
            "content_html": "<p><img data-src=\"1.jpg\" alt></p>\n",
            "tags": [
                "嵌入式面试八股文",
                "嵌入式面试八股文"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2024/03/19/baguwen/1-1-C%E8%AF%AD%E8%A8%80-%E5%86%85%E5%AD%98/",
            "url": "https://littlestory1.github.io/2024/03/19/baguwen/1-1-C%E8%AF%AD%E8%A8%80-%E5%86%85%E5%AD%98/",
            "title": "1-1-C语言-内存",
            "date_published": "2024-03-18T17:09:00.000Z",
            "content_html": "<p><img data-src=\"1.jpg\" alt></p>\n<h2 id=\"c语言内存\"><a class=\"anchor\" href=\"#c语言内存\">#</a> C 语言 —— 内存</h2>\n<h3 id=\"内存分配方式\"><a class=\"anchor\" href=\"#内存分配方式\">#</a> 内存分配方式</h3>\n<blockquote>\n<ol>\n<li><strong>栈内存分配（Stack Allocation）</strong>：</li>\n</ol>\n<ul>\n<li>栈内存是一种自动分配和释放的内存，用于存储局部变量和函数调用的上下文信息。</li>\n<li>变量在函数内部声明时，存储在栈内存中。栈的特性是后进先出（LIFO），所以最后进入栈的变量会最先被释放。</li>\n</ul>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">someFunction</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">int</span> x<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 在栈上分配内存</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token comment\">// 函数执行完毕后，x 的内存会被自动释放</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><ol start=\"2\">\n<li><strong>堆内存分配（Heap Allocation）</strong>：</li>\n</ol>\n<ul>\n<li>堆内存是一种动态分配和释放的内存，用于存储程序运行时需要动态分配的数据。</li>\n<li>使用 <code>malloc()</code> 、 <code>calloc()</code> 、 <code>realloc()</code>  等函数在堆上分配内存，并使用  <code>free()</code>  函数释放堆内存。</li>\n</ul>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>ptr <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token function\">malloc</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 在堆上分配内存</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// 使用完毕后，需要手动释放内存</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">free</span><span class=\"token punctuation\">(</span>ptr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><ol start=\"3\">\n<li><strong>全局变量和静态变量分配（Static and Global Variables）</strong>：</li>\n</ol>\n<ul>\n<li>全局变量和静态变量存储在静态存储区，它们在程序的整个生命周期内存在。</li>\n<li>全局变量在所有函数之外声明，而静态变量在函数内部使用  <code>static</code>  关键字声明。</li>\n</ul>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> globalVar<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 全局变量，在静态存储区分配内存</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">someFunction</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">static</span> <span class=\"token keyword\">int</span> staticVar<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 静态变量，在静态存储区分配内存</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></blockquote>\n<h3 id=\"堆和栈的区别\"><a class=\"anchor\" href=\"#堆和栈的区别\">#</a> 堆和栈的区别</h3>\n<blockquote>\n<ol>\n<li><strong>生存周期</strong>:</li>\n</ol>\n<ul>\n<li><strong>栈</strong>：栈上的变量的生命周期通常局限于函数的执行期间。当函数返回时，栈上的局部变量会被销毁，内存被释放。</li>\n<li><strong>堆</strong>：堆上分配的内存的生命周期可以长于任何特定函数调用，通常由程序员来管理。内存只有在显式释放时才会被回收。</li>\n</ul>\n<ol start=\"2\">\n<li><strong>大小限制</strong>:</li>\n</ol>\n<ul>\n<li><strong>栈</strong>：栈的大小通常受限于编译器或操作系统的设置，较小。因此，栈适合存储相对较小的数据结构。</li>\n<li><strong>堆</strong>：堆的大小通常受系统内存的限制，可以分配较大的内存块，适合存储大型数据结构。</li>\n</ul>\n<ol start=\"3\">\n<li><strong>访问速度</strong>:</li>\n</ol>\n<ul>\n<li><strong>栈</strong>：栈上的内存访问速度较快，因为它是线性分配，且栈上的数据通常存储紧凑。</li>\n<li><strong>堆</strong>：堆上的内存访问速度较慢，因为它是动态分配的，数据可能分散存储在内存中。</li>\n</ul>\n<ol start=\"4\">\n<li><strong>分配方式</strong>:</li>\n</ol>\n<ul>\n<li><strong>栈</strong>：栈上的内存分配和释放是自动的，不需要程序员干预。</li>\n<li><strong>堆</strong>：堆上的内存需要程序员手动分配和释放，使用  <code>malloc()</code> 、 <code>free()</code>  等函数。</li>\n</ul>\n</blockquote>\n<h3 id=\"栈在c语言中的作用\"><a class=\"anchor\" href=\"#栈在c语言中的作用\">#</a> 栈在 c 语言中的作用</h3>\n<blockquote>\n<ol>\n<li>用来保存临时变量，临时变量包括函数参数，函数内部定义的临时变量</li>\n<li>多线程编程的基础就是栈，每个线程多最少有自己的专属的栈，用来保存本线程运行时各个函数的临时变量</li>\n</ol>\n</blockquote>\n<h3 id=\"c的内存管理\"><a class=\"anchor\" href=\"#c的内存管理\">#</a> c++ 的内存管理</h3>\n<blockquote>\n<p>在 c++ 中虚拟内存分为代码段、数据段、bss 段、堆、共享区、栈</p>\n<ol>\n<li>代码段：包括只读存储去和文本区，其中只读存储区字符串常量，文本区存储程序的机械代码</li>\n<li>数据段：全局变量、静态变量（全局、局部）</li>\n<li>BSS 段：未初始化的全局变量和静态变量（全局、局部），以及所有被初始化为 0 的全局变量和静态变量</li>\n<li>堆：调用 new/malloc 申请的内存空间，地址由低地址向高地址扩张</li>\n<li>栈：局部变量、函数的返回值，函数的参数，地址由高地址向低地址扩张</li>\n</ol>\n</blockquote>\n<h3 id=\"内存泄漏\"><a class=\"anchor\" href=\"#内存泄漏\">#</a> 内存泄漏</h3>\n<blockquote>\n<p>简单来说就是申请了内存，不使用之后并没有释放内存，或者说，指向申请的内存的指针突然又去指向别的地方，导致找不到申请的内存，</p>\n<p><strong>影响</strong></p>\n<p>随着程序运行时间越长，占用内存越多，最终用完内存，导致系统崩溃</p>\n<p><strong>减少内存泄漏</strong></p>\n<ol>\n<li>良好的编码习惯，使用内存分配的函数，一但使用完毕之后就要记得使用对应的函数是否掉</li>\n<li>将分配的内存的指针以链表的形式自行管理，使用之后从链表中删除，程序结束时可以检查改链表</li>\n<li>使用智能指针</li>\n</ol>\n</blockquote>\n<h3 id=\"字节对齐问题\"><a class=\"anchor\" href=\"#字节对齐问题\">#</a> 字节对齐问题</h3>\n<blockquote>\n<ol>\n<li><strong>对齐要求</strong>：计算机体系结构规定了数据类型的对齐要求，通常以字节为单位。例如，一个 32 位体系结构可能需要数据类型的存储地址是其大小的整数倍，比如 4 字节对齐或 8 字节对齐。</li>\n<li><strong>未对齐访问</strong>：如果数据没有按照对齐要求存储在内存中，访问该数据可能会导致性能损失或硬件要求，并可能导致错误。在这种情况下，需要将数据移动到字节对齐的地址进行访问。</li>\n</ol>\n<p><strong>常见就是求复合类型大小，比如结构体、联合体</strong></p>\n</blockquote>\n<h3 id=\"c语言函数参数压栈顺序\"><a class=\"anchor\" href=\"#c语言函数参数压栈顺序\">#</a> C 语言函数参数压栈顺序</h3>\n<blockquote>\n<p>C 语言中，函数参数的压栈顺序通常是从右到左，也就是从最后一个参数开始压栈，依次向前。这是因为 C 语言的调用约定是 &quot;cdecl&quot;（C Declaration），按照这个约定，函数的调用者（调用函数的地方）会将参数从右到左依次推入栈中，然后调用函数。</p>\n<p>举个例子，假设有一个如下所示的函数：</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">addNumbers</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> a<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> b<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> c<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>   <span class=\"token keyword\">return</span> a <span class=\"token operator\">+</span> b <span class=\"token operator\">+</span> c<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>如果在另一个函数中调用 <code>addNumbers</code>  函数，假设要计算 <code>addNumbers(1, 2, 3)</code> ，参数的压栈顺序是这样的：</p>\n<ol>\n<li>首先，数字 3（参数 c）被推入栈中。</li>\n<li>然后，数字 2（参数 b）被推入栈中。</li>\n<li>最后，数字 1（参数 a）被推入栈中。</li>\n</ol>\n</blockquote>\n<h3 id=\"可能内存溢出的函数\"><a class=\"anchor\" href=\"#可能内存溢出的函数\">#</a> 可能内存溢出的函数</h3>\n<blockquote>\n<ol>\n<li><strong> <code>strcat</code> </strong>:</li>\n</ol>\n<ul>\n<li><code>strcat</code>  用于将一个字符串附加到另一个字符串的末尾。</li>\n<li>可能导致内存溢出，因为它不会检查目标字符串的容量，如果目标字符串不足以容纳被附加的内容，就会溢出。</li>\n</ul>\n<p>改进方法：使用  <code>strncat</code>  函数，该函数接受一个额外参数，指定要附加的最大字符数，从而避免溢出。</p>\n<ol start=\"2\">\n<li><strong> <code>strncat</code> </strong>:</li>\n</ol>\n<ul>\n<li><code>strncat</code>  具有改进版的  <code>strcat</code> ，可以控制附加的字符数。</li>\n<li>仍然需要小心，确保指定的字符数不会超过目标字符串的容量。</li>\n</ul>\n<ol start=\"3\">\n<li><strong> <code>strcmp</code> </strong>:</li>\n</ol>\n<ul>\n<li><code>strcmp</code>  用于比较两个字符串是否相等。</li>\n<li>不会导致内存溢出，但可能导致无限循环或错误，如果比较的字符串没有正确的终止符。</li>\n</ul>\n<p>改进方法：使用  <code>strncmp</code>  函数，并始终确保比较的字符串以 null 结尾。</p>\n<ol start=\"4\">\n<li><strong> <code>strcpy</code> </strong>:</li>\n</ol>\n<ul>\n<li><code>strcpy</code>  用于将一个字符串复制到另一个字符串。</li>\n<li>可能导致内存溢出，因为它不会检查目标字符串的容量，如果目标字符串不足以容纳被复制的内容，就会溢出。</li>\n</ul>\n<p>改进方法：使用  <code>strncpy</code>  函数，该函数接受一个额外参数，指定要复制的最大字符数，从而避免溢出。</p>\n</blockquote>\n<h3 id=\"内存申请函数\"><a class=\"anchor\" href=\"#内存申请函数\">#</a> 内存申请函数</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 申请堆内存</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span><span class=\"token function\">malloc</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">size_t</span> size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 申请 size_t 个字节内存</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">free</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span>ptr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 释放内存，但是指针还是可以用</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span><span class=\"token function\">calloc</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">size_t</span> nmemb<span class=\"token punctuation\">,</span> <span class=\"token class-name\">size_t</span> size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 申请 nmemb 快内存，每块 size_t 个字节</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span><span class=\"token function\">realloc</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span>ptr<span class=\"token punctuation\">,</span> <span class=\"token class-name\">size_t</span> size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// 申请内存，重新申请 size_t 字节内存，</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span><span class=\"token function\">reallocarray</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span>ptr<span class=\"token punctuation\">,</span> <span class=\"token class-name\">size_t</span> nmemb<span class=\"token punctuation\">,</span> <span class=\"token class-name\">size_t</span> size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure></blockquote>\n",
            "tags": [
                "嵌入式面试八股文",
                "嵌入式面试八股文"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2024/03/19/baguwen/1-2-C%E8%AF%AD%E8%A8%80-%E6%8C%87%E9%92%88&%E6%95%B0%E7%BB%84/",
            "url": "https://littlestory1.github.io/2024/03/19/baguwen/1-2-C%E8%AF%AD%E8%A8%80-%E6%8C%87%E9%92%88&%E6%95%B0%E7%BB%84/",
            "title": "1-2-C语言-指针&数组",
            "date_published": "2024-03-18T17:09:00.000Z",
            "content_html": "<p><img data-src=\"1.jpg\" alt></p>\n<h2 id=\"c语言指针数组\"><a class=\"anchor\" href=\"#c语言指针数组\">#</a> C 语言 —— 指针 &amp; 数组</h2>\n<h3 id=\"指针\"><a class=\"anchor\" href=\"#指针\">#</a> 指针</h3>\n<blockquote>\n<p>指针是一种编程概念，它是一个变量或数据类型，用于存储内存地址。指针允许程序直接访问和操作内存中的数据，而不仅仅是访问变量的值。指针通常在低级编程语言（如 C 和 C++）中使用，以及某些高级编程语言中的底层编程任务中。</p>\n<p>关键要点关于指针包括：</p>\n<ol>\n<li><strong>内存地址</strong>：指针存储一个内存地址，该地址指向计算机内存中的某个位置。</li>\n<li><strong>指向</strong>：指针可以指向内存中的数据，这可以是基本数据类型（如整数、字符）或复杂的数据结构（如数组、结构体）。</li>\n<li><strong>解引用</strong>：通过解引用指针，可以访问指针所指向的内存地址上的值。解引用操作使用  <code>*</code>  符号。</li>\n<li><strong>地址运算</strong>：指针可以进行地址运算，例如指针加法或减法，以访问相邻内存位置。</li>\n<li><strong>动态内存分配</strong>：指针在动态内存分配中非常有用，允许程序在运行时分配和释放内存，避免静态内存分配的限制。</li>\n<li><strong>传递参数</strong>：指针允许将变量的地址传递给函数，以便在函数内部修改变量的值。</li>\n</ol>\n<p><strong>好处</strong></p>\n<ol>\n<li>指针可以动态分配内存</li>\n<li>在链表中可以方便修改链表的节点</li>\n<li>解析字符串</li>\n<li>相同类型的指针可以直接复制</li>\n</ol>\n<p><strong>调用 Free 释放内存后，指针还能用吗</strong></p>\n<p>Free 释放掉内存后，只是把内存的使用权就被归还给系统，内存里面的东西可能被清除也可能是垃圾值，但是指向这个内存的指针还是指向这块内存，并不会 NULL</p>\n<p><strong>指针不能加指针</strong></p>\n<p>指针之间可以做减法，但不能做加法</p>\n<p><strong>空指针是指指向地址为 0 的地方</strong></p>\n</blockquote>\n<h3 id=\"数组\"><a class=\"anchor\" href=\"#数组\">#</a> 数组</h3>\n<blockquote>\n<p><strong>初始化</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> a<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 不允许</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> b<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token operator\">=</span><span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 可以</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> c<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 可以</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">int</span> c<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 不可以</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">int</span> d<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 不允许，第二个 [] 必须填，不管有没有初始化</span></pre></td></tr></table></figure><p><strong>数组名 num  /  &amp;num 的区别</strong></p>\n<blockquote>\n<p><strong>对于一维数组来说</strong></p>\n<p>num+1 是偏移到下个元素，&amp;num+1 是偏移整个数组</p>\n<p><strong>对于二维数组来说</strong></p>\n<p>num+1 是偏移一个一维数组，&amp;num+1 是整个数组</p>\n</blockquote>\n<p><strong>数组下标是负数</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> a<span class=\"token punctuation\">[</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>p <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>a<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">for</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i<span class=\"token operator\">=</span><span class=\"token operator\">-</span><span class=\"token number\">4</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">&lt;=</span><span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>\t<span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token operator\">%</span>d <span class=\"token operator\">%</span>d \\n\"<span class=\"token punctuation\">,</span> p<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>p<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\">// 0  1310572</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\">// 1  1310576</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token comment\">// 2  1310580</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>……</pre></td></tr></table></figure><p><strong>二维数组</strong></p>\n<blockquote>\n<p>int a[3][3];</p>\n<ol>\n<li>int a [3][3]; 表示是个三行三列的二维数组</li>\n<li>数组名表示数组首元素的地址，即第 0 行第 0 个地址</li>\n<li>a+1 表示地址偏移一个一维数组的地址，即三列<em> int 大小 = 3</em>4 = 12</li>\n<li>*a 表示去二维变一维，*a 就相当于一维数组的数组名，比如 *a +1 表示第 0 行下标为 1 的元素地址，只是偏移一个 Int 地址</li>\n<li>若要表示 a [2][2] 的元素 即 *(*(a+2)+2)</li>\n</ol>\n</blockquote>\n</blockquote>\n<h3 id=\"指针的运算\"><a class=\"anchor\" href=\"#指针的运算\">#</a> 指针的运算</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 例子 1：</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>ptr<span class=\"token punctuation\">;</span><span class=\"token comment\">// 假设指针指向的地址是 0x 00 00 00 00</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>Ptr<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 运算之后指针指向 0x 00 00 00 04</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>Char <span class=\"token operator\">*</span>p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>P<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// 地址偏移 1</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\">// 注意：对于一级指针的 ++ 操作偏移量要看指针指向的是什么类型</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token comment\">// 对应二级指针偏移量，对于 32 系统是 4 个字节，因为二级指针指向的类型就是指针，所以永远是一个指针类型的大小</span></pre></td></tr></table></figure><figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 例子 2：</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span><span class=\"token string\">&lt;stdio.h></span> </span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> </pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#123;</span> </pre></td></tr><tr><td data-num=\"5\"></td><td><pre>   <span class=\"token keyword\">char</span> a<span class=\"token punctuation\">[</span><span class=\"token number\">20</span><span class=\"token punctuation\">]</span><span class=\"token operator\">=</span><span class=\"token string\">\"You_are_a_girl\"</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"6\"></td><td><pre>   <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>p<span class=\"token operator\">=</span>a<span class=\"token punctuation\">;</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token operator\">*</span>ptr<span class=\"token operator\">=</span><span class=\"token operator\">&amp;</span>p<span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"7\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"**ptr=%c\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span>ptr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"8\"></td><td><pre>   ptr<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"9\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"**ptr=%c\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span>ptr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\">// 在这个例子中是无法确定二级指针 ++ 之后指向的地址内容，因为二级指针 (ptr) 指针指向的一级指针的地址，如果二级指针 (ptr)++ 之后，那么就会指向一级指针的后 4 个字节 (对于 32 位操作系统来说指针类型是 4 字节)，至于这个地址里面是啥无从得知</span></pre></td></tr></table></figure><figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// *p++   *(p++)     (*p)++     *++p   ++*p  的运算</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> num<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token number\">1.</span> 后<span class=\"token operator\">++</span>先不用管，即先把地址里面的值给别人，再去<span class=\"token operator\">++</span>，可以是地址或值<span class=\"token punctuation\">(</span>看括号是否包住<span class=\"token operator\">*</span>p<span class=\"token punctuation\">,</span>是则是值<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span>，后<span class=\"token operator\">++</span>有三种如下：</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>p<span class=\"token punctuation\">)</span><span class=\"token operator\">++</span>   地址前后都不会变化，变化的是地址里面的值，先赋值给别人，<span class=\"token operator\">*</span>P再<span class=\"token operator\">++</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span>p<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span>和<span class=\"token operator\">*</span>p<span class=\"token operator\">++</span>一样  地址发生变化，先把<span class=\"token operator\">*</span>P赋值给别人，再<span class=\"token operator\">++</span>地址</pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token number\">2.</span>前<span class=\"token operator\">++</span>，先<span class=\"token operator\">++</span>操作，可以是<span class=\"token operator\">++</span>地址或者值，<span class=\"token punctuation\">(</span><span class=\"token operator\">++</span>符号靠近p就是地址<span class=\"token operator\">++</span>，靠近<span class=\"token operator\">*</span>P就是值<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span>，再把值给别人</pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token operator\">*</span><span class=\"token operator\">++</span>p   地址发生改变，先把地址<span class=\"token operator\">++</span>，再把地址变化后的里面的值给别人</pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token operator\">++</span><span class=\"token operator\">*</span>p   地址不发生变化，<span class=\"token operator\">*</span>P的值<span class=\"token operator\">++</span>之后再赋值给别人</pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>注意<span class=\"token operator\">:</span>指针<span class=\"token operator\">++</span><span class=\"token punctuation\">,</span>到底加几个字节要根据指针指向的类型决定，指针在<span class=\"token number\">32</span>系统中永远是<span class=\"token number\">4</span>个字节</pre></td></tr><tr><td data-num=\"13\"></td><td><pre>举例子：</pre></td></tr><tr><td data-num=\"14\"></td><td><pre>Int <span class=\"token operator\">*</span> a<span class=\"token punctuation\">;</span><span class=\"token comment\">// 假设指针指向的地址 0</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>a<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// 此时指针指向后移 4 个字节，即指向 4</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>Char <span class=\"token operator\">*</span>b<span class=\"token punctuation\">;</span><span class=\"token comment\">// 假设指针指向的地址 0</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>b<span class=\"token operator\">++</span>；<span class=\"token comment\">// 此时指针指向后移 1 个字节，即指向 1</span></pre></td></tr></table></figure><figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//sizeof (数组名) 和 sizeof (&amp; 数组)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> Num<span class=\"token punctuation\">[</span><span class=\"token number\">100</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%ld\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>Num<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//400</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%ld\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>Num<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//8 起始就是打印 int * 指针大小</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%ld\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//8</span></pre></td></tr></table></figure></blockquote>\n<h3 id=\"指针数组\"><a class=\"anchor\" href=\"#指针数组\">#</a> 指针数组</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 首先是个数组，这个数组里的元素是指针</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>p <span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> a<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span><span class=\"token operator\">=</span><span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>p<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token operator\">=</span><span class=\"token operator\">&amp;</span>a<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">*</span>p<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 首先是个指针，这个指针指向数组例如：</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">Int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>p<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// 表示一个指向有 4 个 int 元素的数组的指针，所以 p+1，加的是 4 个 int</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">int</span> num<span class=\"token punctuation\">[</span><span class=\"token number\">8</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span><span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">,</span><span class=\"token number\">7</span><span class=\"token punctuation\">,</span><span class=\"token number\">8</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span> <span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>p <span class=\"token operator\">=</span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//8 因为 p 是指针，64 位系统 8 个字节</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p\\n\"</span><span class=\"token punctuation\">,</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffe11d8a4e0 </span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p\\n\"</span><span class=\"token punctuation\">,</span>p<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffe11d8a4f0 // 加的是指针指向的类型大小，这里指针指向的是有四个 4int 元素的数组，所以加的是 16 个字节</span></pre></td></tr></table></figure><figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 双指针</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> b<span class=\"token punctuation\">[</span><span class=\"token number\">12</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">,</span><span class=\"token number\">7</span><span class=\"token punctuation\">,</span><span class=\"token number\">8</span><span class=\"token punctuation\">,</span><span class=\"token number\">9</span><span class=\"token punctuation\">,</span><span class=\"token number\">10</span><span class=\"token punctuation\">,</span><span class=\"token number\">11</span><span class=\"token punctuation\">,</span><span class=\"token number\">12</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>p <span class=\"token operator\">=</span> b<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token operator\">++</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 5</span></pre></td></tr></table></figure></blockquote>\n<h3 id=\"指针函数\"><a class=\"anchor\" href=\"#指针函数\">#</a> 指针函数</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 函数的返回值是个指针类型</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span> <span class=\"token function\">fun</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> x<span class=\"token punctuation\">,</span><span class=\"token keyword\">int</span> y<span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>   </pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></blockquote>\n<h3 id=\"函数指针\"><a class=\"anchor\" href=\"#函数指针\">#</a> 函数指针</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>pf<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">float</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">// 函数指针调用函数事注意以下几点：</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token number\">1.</span>\t函数类型必须和函数指针的类型一样，比如参数类型，返回值</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token number\">2.</span>\t给函数指针赋值是可以<span class=\"token operator\">&amp;</span>也可以不要</pre></td></tr></table></figure></blockquote>\n<h3 id=\"指针和数组的区别\"><a class=\"anchor\" href=\"#指针和数组的区别\">#</a> 指针和数组的区别</h3>\n<blockquote>\n<ol>\n<li><strong>数据类型</strong>:</li>\n</ol>\n<ul>\n<li>指针是一种数据类型，用于存储内存地址。指针可以指向不同数据类型的内存位置。</li>\n<li>数组是一种数据结构，用于存储相同数据类型的一组连续内存单元。</li>\n</ul>\n<ol start=\"2\">\n<li><strong>大小</strong>:</li>\n</ol>\n<ul>\n<li>指针的大小通常与系统架构相关，它存储一个内存地址，因此大小在不同系统上可能会有所不同。</li>\n<li>数组的大小是由其包含的元素数量决定，每个元素的大小也是相同的。</li>\n</ul>\n<ol start=\"3\">\n<li><strong>初始化和赋值</strong>:</li>\n</ol>\n<ul>\n<li>指针需要显式初始化为一个有效的内存地址，可以通过将其设置为某个变量的地址来初始化。</li>\n<li>数组在声明时需要指定大小，而且在创建时会自动初始化，可以直接为数组元素赋值。</li>\n</ul>\n<ol start=\"4\">\n<li><strong>地址运算</strong>:</li>\n</ol>\n<ul>\n<li>指针允许进行地址运算，例如指针加法或减法，以访问内存中的相邻位置。</li>\n<li>数组的元素在内存中是连续存储的，因此可以通过索引来访问不同的元素。</li>\n</ul>\n<ol start=\"5\">\n<li><strong>传递给函数</strong>:</li>\n</ol>\n<ul>\n<li>指针可以用于将变量的地址传递给函数，以便在函数内部修改变量的值。</li>\n<li>数组在传递给函数时通常会退化为指针，因此函数接收到的是指向数组第一个元素的指针。</li>\n</ul>\n<ol start=\"6\">\n<li><strong>动态内存分配</strong>:</li>\n</ol>\n<ul>\n<li>指针可用于动态内存分配，例如使用  <code>malloc</code>  或  <code>new</code>  来分配内存，然后通过指针访问分配的内存。</li>\n<li>数组的大小通常在编译时确定，但 C99 标准引入了可变长度数组（VLA），允许在运行时指定数组大小。</li>\n</ul>\n</blockquote>\n<h3 id=\"指针和引用的区别\"><a class=\"anchor\" href=\"#指针和引用的区别\">#</a> 指针和引用的区别</h3>\n<blockquote>\n<ol>\n<li><strong>指针</strong>：</li>\n</ol>\n<ul>\n<li>指针是一个变量，它存储另一个变量的内存地址。</li>\n<li>指针可以为空（null），也可以重新分配给指向不同的变量。</li>\n<li>指针需要使用解引用操作符  <code>*</code>  来访问所指向的值。</li>\n<li>指针可以进行指针算术，如指针加法或减法。</li>\n<li>指针可以指向不同类型的对象，但需要进行强制类型转换。</li>\n<li>指针可能需要显式地管理内存，包括分配和释放内存。</li>\n</ul>\n<ol start=\"2\">\n<li><strong>引用</strong>：</li>\n</ol>\n<ul>\n<li>引用是一个别名，它为已经存在的变量提供了另一个名称。</li>\n<li>引用在创建时必须与现有变量绑定，无法改变绑定到不同的变量。</li>\n<li>引用的语法更简洁，不需要解引用操作符，直接使用引用就可以访问所绑定的值。</li>\n<li>引用不支持指针算术。</li>\n<li>引用通常用于传递参数给函数，以便在函数内部修改参数的值。</li>\n<li>引用不需要显式管理内存，不涉及内存分配和释放。</li>\n</ul>\n<p><strong>引用区别于指针的特性是</strong> ：</p>\n<ol>\n<li>不存在空引用（保证不操作空指针）</li>\n<li>必须初始化（保证不是野指针）</li>\n<li>一个引用永远指向他初始化的那个对象（保证指针值不变）</li>\n</ol>\n</blockquote>\n<h3 id=\"野指针\"><a class=\"anchor\" href=\"#野指针\">#</a> 野指针</h3>\n<blockquote>\n<p><strong>野指针</strong>：是指指针指向的地址是不确定的；</p>\n<p>野指针（Dangling Pointer）通常是指指针变量存储了一个无效的内存地址，也就是它指向的内存区域可能已经被释放或不再有效。野指针的操作是不安全的，因为它们可能导致未定义的行为或程序崩溃。</p>\n<p>野指针一般来说可以被重新赋值，但这并不会解决野指针的问题。重新赋值一个野指针只是改变了它的目标地址，但仍然可能会导致访问无效内存。在 C 和 C++ 中，遵循以下最佳实践来处理野指针：</p>\n<ol>\n<li><strong>避免野指针</strong>：在使用指针前，确保它指向有效的内存区域。不要让指针指向已释放的内存或未分配的内存。</li>\n<li><strong>初始化指针</strong>：在声明指针时，始终将其初始化为 <code>NULL</code> （C 语言）或 <code>nullptr</code> （C++ 语言）。这可以帮助你检测是否有野指针。</li>\n<li><strong>谨慎使用已释放的内存</strong>：如果确实要使用已释放的内存，确保在释放内存后不再访问它。</li>\n<li><strong>不要多次释放相同的内存</strong>：释放内存后，不要再次释放相同的内存块，否则会导致问题。</li>\n</ol>\n<p><strong>原因</strong>：</p>\n<p>释放内存之后，指针没有及时置空</p>\n<p><strong>避免：</strong></p>\n<ol>\n<li>初始化置 NULL</li>\n<li>申请内存后判空</li>\n<li>指针释放后置 NULL</li>\n<li>使用智能指针</li>\n</ol>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>p1 <span class=\"token operator\">=</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 初始化置 NULL</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>p1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token function\">calloc</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 申请 n 个 int 内存空间同时初始化为 0 </span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">assert</span><span class=\"token punctuation\">(</span>p1 <span class=\"token operator\">!=</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 判空，防错设计</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">free</span><span class=\"token punctuation\">(</span>p1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  </pre></td></tr><tr><td data-num=\"5\"></td><td><pre>p1 <span class=\"token operator\">=</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 释放后置空</span></pre></td></tr></table></figure></blockquote>\n<h3 id=\"指针-const\"><a class=\"anchor\" href=\"#指针-const\">#</a> 指针 &amp; const</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span><span class=\"token operator\">*</span> p<span class=\"token punctuation\">;</span>         <span class=\"token comment\">// 常量指针 -----> 指针指向的地址的内容不可以改变</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token keyword\">const</span> <span class=\"token operator\">*</span>p<span class=\"token punctuation\">;</span>         <span class=\"token comment\">// 常量指针</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">const</span> p<span class=\"token punctuation\">;</span>        <span class=\"token comment\">// 指针常量 --------> 指针指向的地址可以不改变</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>  <span class=\"token keyword\">const</span> p<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 指向常量的常量指针</span></pre></td></tr></table></figure></blockquote>\n<h3 id=\"指针减指针\"><a class=\"anchor\" href=\"#指针减指针\">#</a> 指针减指针</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 地址相减 =  （地址 a - 地址 b）/sizeof（指针指向的类型）</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> a<span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>a<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>a<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>a<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>p<span class=\"token punctuation\">,</span> <span class=\"token operator\">*</span>q<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>p <span class=\"token operator\">=</span> a<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>q <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>a<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p\\n\"</span><span class=\"token punctuation\">,</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffe80e38b0c   </span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p\\n\"</span><span class=\"token punctuation\">,</span>q<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffe80e38b14   </span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span>q<span class=\"token operator\">-</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//2        ( q - p) /sizeof(int )</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token comment\">// 那么就有</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>a<span class=\"token punctuation\">[</span>q<span class=\"token operator\">-</span>p<span class=\"token punctuation\">]</span>  <span class=\"token operator\">=</span>  a<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">2</span></pre></td></tr></table></figure></blockquote>\n<h3 id=\"指针作为函数参数传递问题\"><a class=\"anchor\" href=\"#指针作为函数参数传递问题\">#</a> 指针作为函数参数传递问题</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 函数 1，交换两个数</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">swap1</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>p<span class=\"token punctuation\">,</span><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>q<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#123;</span>\t</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>\t<span class=\"token keyword\">int</span> num <span class=\"token operator\">=</span>  <span class=\"token operator\">*</span>p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>\t<span class=\"token operator\">*</span>p <span class=\"token operator\">=</span><span class=\"token operator\">*</span>q<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>\t<span class=\"token operator\">*</span>q  <span class=\"token operator\">=</span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\">// 函数 2，让 p 指针指向 a，想重新给 p 赋值为 90，之后再交换 p,q</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">swap</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>p<span class=\"token punctuation\">,</span><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>q<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token punctuation\">&#123;</span>\t</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>   <span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span><span class=\"token number\">90</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>\tp <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>a<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>\t<span class=\"token keyword\">int</span> num <span class=\"token operator\">=</span>  <span class=\"token operator\">*</span>p<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>\t<span class=\"token operator\">*</span>p <span class=\"token operator\">=</span><span class=\"token operator\">*</span>q<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>\t<span class=\"token operator\">*</span>q  <span class=\"token operator\">=</span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>\t<span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span>b <span class=\"token operator\">=</span><span class=\"token number\">3</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>\t<span class=\"token keyword\">int</span> <span class=\"token operator\">*</span> j <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>a<span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 指针 j 指向 a</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>\t<span class=\"token keyword\">int</span> <span class=\"token operator\">*</span> k <span class=\"token operator\">=</span><span class=\"token operator\">&amp;</span>b<span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 指针 k 指向 b</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>\t<span class=\"token function\">swap</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">,</span>k<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 调用函数</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>\t<span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"a =%d   b= %d\\n\"</span><span class=\"token punctuation\">,</span>a<span class=\"token punctuation\">,</span>b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// a = 2 b = 90;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>  <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre><span class=\"token comment\">// 于函数 swap1 我们可以正常交换两个值，但是 swap 函数却不是我们想要的，我们想要的答案是 a = 3 b = 90; 可是发现，a 的值压根没变，这是为什么呢？</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre></pre></td></tr><tr><td data-num=\"29\"></td><td><pre><span class=\"token comment\">// 在 swap 函数中，你将指针 p 指向了一个局部变量 a，而这个局部变量在 swap 函数执行完毕后将被销毁。这会导致指针 p 指向一个不再有效的内存位置</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>总结：</pre></td></tr><tr><td data-num=\"32\"></td><td><pre>如果在函数形参里的指针变量不修改指向，那么就会影响传递过来的指针</pre></td></tr></table></figure><figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">fun</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>s<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>   <span class=\"token keyword\">char</span> a<span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>   <span class=\"token function\">strcpy</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> <span class=\"token string\">\"STRING\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>   s <span class=\"token operator\">=</span> a<span class=\"token punctuation\">;</span><span class=\"token comment\">// 修改了形参指针指向，就不会影响传递过来指针</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>   <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>p <span class=\"token operator\">=</span> <span class=\"token string\">\"PROGRAM\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>   <span class=\"token function\">fun</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%s\\n\"</span><span class=\"token punctuation\">,</span> p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//PROGRAM</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token comment\">// 拓展：通过二级指针操作</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">fun</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token operator\">*</span>s<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>   <span class=\"token keyword\">char</span> a<span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>   <span class=\"token function\">strcpy</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> <span class=\"token string\">\"STRING\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>\t<span class=\"token operator\">*</span>s <span class=\"token operator\">=</span> a<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>  <span class=\"token comment\">// *s = \"string\";</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>   <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>p <span class=\"token operator\">=</span> <span class=\"token string\">\"PROGRAM\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>   <span class=\"token function\">fun</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%s\\n\"</span><span class=\"token punctuation\">,</span> p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 打印空白</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>\t<span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token comment\">// 在这里我们通过把一级指针的地址传递给函数，函数二级形参来接受，那么 * s 表示的就是指针 p 指向的地址，可以看出这里直接就操作 p 的指针指向，所以如果  *s = “string” 那么指针 p 就会指向”string” 的地址</span></pre></td></tr></table></figure></blockquote>\n<h3 id=\"二维数组和数组指针\"><a class=\"anchor\" href=\"#二维数组和数组指针\">#</a> 二维数组和数组指针</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>   <span class=\"token comment\">/* 二维数组和数组指针 */</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>   <span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>   <span class=\"token keyword\">int</span> s<span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token operator\">=</span><span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">7</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">9</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">7</span><span class=\"token punctuation\">,</span><span class=\"token number\">9</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>   p <span class=\"token operator\">=</span> s<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p addr is = %p\\n\"</span><span class=\"token punctuation\">,</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffde8cdf0a0</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"s addr is = %p\\n\"</span><span class=\"token punctuation\">,</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffde8cdf0a0</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>   <span class=\"token comment\">/* 可以发现 p+1 和 s+1 是一样的都是加一个一维数组 */</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"p + 1 addr is = %p\\n\"</span><span class=\"token punctuation\">,</span>p <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffde8cdf0ac</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"s + 1 addr is = %p\\n\"</span><span class=\"token punctuation\">,</span>s <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffde8cdf0ac</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>   <span class=\"token comment\">/* 可以发现使用 p 表示二维数组的元素和二维数组名表示元素是一样的用法 */</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"*(*(p + 1))  is = %d\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span>p <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//*(*(p + 1))  is = 4</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"*(*(s + 1))  is = %d\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span>s <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//*(*(s + 1))  is = 4</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"*(p[1]+0)  is = %d\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token operator\">+</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//*(p[1]+0)  is = 4</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"*(s[1]+1)  is = %d\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//*(s[1]+1)  is = 9</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>   <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre></pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token comment\">// 一维数组：</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token keyword\">int</span>  num<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>   </pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p \\n\"</span><span class=\"token punctuation\">,</span>num<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  \t\t<span class=\"token comment\">//0x7fffe2a8cde8</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p \\n\"</span><span class=\"token punctuation\">,</span>num<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\t\t<span class=\"token comment\">//0x7fffe2a8cdec   </span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p \\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">&amp;</span>num<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  \t<span class=\"token comment\">//0x7fffe2a8cdf0 </span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token comment\">// 可以看出：</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>num <span class=\"token operator\">+</span><span class=\"token number\">1</span> 加的是一个Int</pre></td></tr><tr><td data-num=\"28\"></td><td><pre><span class=\"token operator\">&amp;</span>num <span class=\"token operator\">+</span> <span class=\"token number\">1</span>加的是整个数组</pre></td></tr><tr><td data-num=\"29\"></td><td><pre></pre></td></tr><tr><td data-num=\"30\"></td><td><pre><span class=\"token comment\">// 二维数组；</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre><span class=\"token keyword\">int</span>  num<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p \\n\"</span><span class=\"token punctuation\">,</span>num<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">//0x7ffe18f73560 </span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p \\n\"</span><span class=\"token punctuation\">,</span>num<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\t <span class=\"token comment\">//0x7ffe18f73568 </span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p \\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">&amp;</span>num<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//0x7ffe18f73570 </span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre></pre></td></tr><tr><td data-num=\"36\"></td><td><pre><span class=\"token comment\">// 可以看出：</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>num <span class=\"token operator\">+</span><span class=\"token number\">1</span> 加的是一个一维</pre></td></tr><tr><td data-num=\"38\"></td><td><pre><span class=\"token operator\">&amp;</span>num <span class=\"token operator\">+</span> <span class=\"token number\">1</span>加的是整个数组</pre></td></tr><tr><td data-num=\"39\"></td><td><pre>   </pre></td></tr><tr><td data-num=\"40\"></td><td><pre><span class=\"token comment\">// 例子   </span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> </pre></td></tr><tr><td data-num=\"42\"></td><td><pre><span class=\"token punctuation\">&#123;</span> </pre></td></tr><tr><td data-num=\"43\"></td><td><pre>   <span class=\"token keyword\">int</span> num<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token operator\">=</span><span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"44\"></td><td><pre>   <span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"45\"></td><td><pre>   p <span class=\"token operator\">=</span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"46\"></td><td><pre></pre></td></tr><tr><td data-num=\"47\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p\\n\"</span><span class=\"token punctuation\">,</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffffad71df0</span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p\\n\"</span><span class=\"token punctuation\">,</span>p<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffffad71dfc</span></pre></td></tr><tr><td data-num=\"49\"></td><td><pre>   </pre></td></tr><tr><td data-num=\"50\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p\\n\"</span><span class=\"token punctuation\">,</span>num<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffffad71df4</span></pre></td></tr><tr><td data-num=\"51\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">*</span>p<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffffad71df4</span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre>\t<span class=\"token comment\">// 注意这里 & amp;p+1</span></pre></td></tr><tr><td data-num=\"53\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%p\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">&amp;</span>num<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//0x7ffffad71e08</span></pre></td></tr><tr><td data-num=\"54\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//1</span></pre></td></tr><tr><td data-num=\"55\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></blockquote>\n",
            "tags": [
                "嵌入式面试八股文",
                "嵌入式面试八股文"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2024/03/19/baguwen/1-3-C%E8%AF%AD%E8%A8%80-%E9%A2%84%E5%A4%84%E7%90%86/",
            "url": "https://littlestory1.github.io/2024/03/19/baguwen/1-3-C%E8%AF%AD%E8%A8%80-%E9%A2%84%E5%A4%84%E7%90%86/",
            "title": "1-3-C语言-预处理",
            "date_published": "2024-03-18T17:09:00.000Z",
            "content_html": "<p><img data-src=\"1.jpg\" alt></p>\n<h2 id=\"c语言预处理\"><a class=\"anchor\" href=\"#c语言预处理\">#</a> C 语言 —— 预处理</h2>\n<h3 id=\"error\"><a class=\"anchor\" href=\"#error\">#</a> #error</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 编译程序时，只要遇到 #error 就会生成一个编译错误提醒，并且停止编译，</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>语法格式<span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">error</span> <span class=\"token expression\">error<span class=\"token operator\">-</span>message</span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>实例<span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">ifdef</span> <span class=\"token expression\">xxx</span></span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">error</span> <span class=\"token expression\">“xxx has been defined”</span></span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">else</span></span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">endif</span></span></pre></td></tr></table></figure></blockquote>\n<h3 id=\"ifndef-define-endif\"><a class=\"anchor\" href=\"#ifndef-define-endif\">#</a> #ifndef #define #endif</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 当项目中有多个 c 文件使用到同一个头文件是，在编译的时候会出现大量的变量，函数声明冲突，解决就是使用</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">ifndef</span> <span class=\"token expression\">_HEAR_H_</span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">_HEAR_H_</span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">endif</span></span></pre></td></tr></table></figure></blockquote>\n<h3 id=\"define和const\"><a class=\"anchor\" href=\"#define和const\">#</a> #define 和 const</h3>\n<blockquote>\n<p>Define 和 const 都可以用于定义常量但以下区别 (<strong>生效时间，内存占用情况，类型检查</strong>)：</p>\n<ol>\n<li>define 只是单纯的文本替换，define 常量的生命生命周期止于编译器，不存在分配内存，存在与程序的代码段</li>\n<li>const 生效于编译的阶段；define 生效于预处理阶段</li>\n<li>Const 修饰的常量处于程序的数据段，在堆栈中分配空间</li>\n<li>Const 有数据类型检查，define 没有</li>\n<li>#define 不可调试，const 能调试</li>\n<li>const 定义的变量在 C 中不是真正的常量</li>\n<li>Const 定义的常量不能作为数组的大小</li>\n</ol>\n</blockquote>\n<h3 id=\"typedef和define\"><a class=\"anchor\" href=\"#typedef和define\">#</a> typedef 和 #define</h3>\n<blockquote>\n<p>原理不同：</p>\n<ol>\n<li>首先 #define 是预处理命令，在预处理阶段只是机械的替换带入字符串，并不会左类型检查，</li>\n<li>typedef 是关键字，作用是给自己的作用域内给一个已经存在的类型起个别名</li>\n<li>#define 没有作用域的限制，只要是之前预定义过的宏，在以后的程序中都可以使用，而 typedef 有自己的作用域</li>\n<li>对指针的操作不同</li>\n</ol>\n</blockquote>\n<h3 id=\"define\"><a class=\"anchor\" href=\"#define\">#</a> #define</h3>\n<blockquote>\n<p><strong>表明一年</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">YEAR</span> <span class=\"token expression\"><span class=\"token punctuation\">(</span><span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">60</span>  <span class=\"token operator\">*</span> <span class=\"token number\">24</span> <span class=\"token operator\">*</span> <span class=\"token number\">365</span><span class=\"token punctuation\">)</span>ul</span></span></pre></td></tr></table></figure><p><strong>标准宏 MIN</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name function\">MIN</span><span class=\"token expression\"><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token punctuation\">(</span>b<span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> <span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></span></span></pre></td></tr></table></figure><p><strong>缺点</strong></p>\n<ol>\n<li>无法进行类型检查</li>\n<li>运算优先级问题</li>\n<li>无法调试</li>\n<li>代码膨胀</li>\n<li>无法操作类的私有数据成员</li>\n</ol>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name function\">m</span><span class=\"token expression\"><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span>b<span class=\"token punctuation\">)</span> a<span class=\"token operator\">*</span>b</span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// #define m (a,b) (a)*(b)// 避免出问题最好加上 ()</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token function\">m</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span><span class=\"token function\">m</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// 实际是这样的：5+1*6</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name function\">sqort</span><span class=\"token expression\"><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span>  <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></span></span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token comment\">// 实例 1： </span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token keyword\">int</span> b <span class=\"token operator\">=</span> <span class=\"token function\">sqort</span><span class=\"token punctuation\">(</span>a<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//((a++) * (a++) )  先给括号赋值 5 之后 a 再 + 1=6</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span>b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//30</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//7</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token comment\">// 实例 2：\t</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token keyword\">int</span> b <span class=\"token operator\">=</span> <span class=\"token function\">sqort</span><span class=\"token punctuation\">(</span><span class=\"token operator\">++</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//(（++a）* (++a)) </span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span>b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//49</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%d\\n\"</span><span class=\"token punctuation\">,</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//7</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>这里主要是考察<span class=\"token operator\">++</span>a和后加加的问题</pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token comment\">// 记住一点：</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token operator\">++</span>a返回的a的引用，a<span class=\"token operator\">++</span>返回的是a加之前的数值</pre></td></tr><tr><td data-num=\"27\"></td><td><pre>a的引用是要等最终的那个a才能确定的</pre></td></tr></table></figure></blockquote>\n<h3 id=\"include\"><a class=\"anchor\" href=\"#include\">#</a> #include</h3>\n<blockquote>\n<p>对于.#include &lt;头文件&gt;，表示是系统文件，编译会先从标准库路径下搜索，编译器设置的头文件路径 --&gt; 系统变量</p>\n<p>对于 #include” 头文件”，当前头文件目录 --&gt; 编译器设置的头文件路径 --&gt; 系统变量</p>\n</blockquote>\n<h3 id=\"c代码编译过程\"><a class=\"anchor\" href=\"#c代码编译过程\">#</a> C 代码编译过程</h3>\n<blockquote>\n<ol>\n<li><strong>预处理（Preprocessing）：</strong></li>\n</ol>\n<ul>\n<li>预处理阶段是在实际编译之前的一个可选步骤，用于处理源代码中的预处理指令，比如  <code>#include</code>  和  <code>#define</code> 。</li>\n<li>预处理器将处理这些指令，并且可能会包含其他文件、进行宏替换等。</li>\n<li>预处理的输出是一个经过处理的源文件，通常以 <code>.i</code>  或 <code>.ii</code>  为扩展名。</li>\n</ul>\n<ol start=\"2\">\n<li><strong>编译（Compiling）：</strong></li>\n</ol>\n<ul>\n<li>编译阶段将预处理后的源代码转换为汇编代码（Assembly Code）。</li>\n<li>编译器（如 GNU Compiler Collection 中的 <code>gcc</code> ）将 C 源代码翻译成汇编语言。</li>\n<li>输出是一个以 <code>.s</code>  为扩展名的汇编代码文件。</li>\n</ul>\n<ol start=\"3\">\n<li><strong>汇编（Assembling）：</strong></li>\n</ol>\n<ul>\n<li>汇编阶段将汇编代码转换为机器语言指令。</li>\n<li>汇编器（如 GNU Assembler 中的 <code>as</code> ）将汇编代码翻译成机器码。</li>\n<li>输出是一个以 <code>.o</code>  或 <code>.obj</code>  为扩展名的目标文件，包含了二进制指令。</li>\n</ul>\n<ol start=\"4\">\n<li><strong>链接（Linking）：</strong></li>\n</ol>\n<ul>\n<li>链接阶段将多个目标文件（例如，多个 C 文件分别编译得到的目标文件）合并为一个可执行文件。</li>\n<li>链接器（如 GNU 的 <code>ld</code>  或 <code>gcc</code>  中的链接器部分）将各个目标文件中的函数和变量引用解析，并创建一个可执行文件。</li>\n<li>链接的输出是一个可执行的二进制文件，可以在操作系统上运行。</li>\n</ul>\n</blockquote>\n<h3 id=\"在头文件中是否可以定义静态变量\"><a class=\"anchor\" href=\"#在头文件中是否可以定义静态变量\">#</a> 在头文件中是否可以定义静态变量</h3>\n<blockquote>\n<p>不可以，因为静态变量是有记忆的，不会随函数结束而结束，所以，如果定义在头文件中，那么就会被多个文件开辟空间，浪费资源或者重新出错</p>\n</blockquote>\n<h3 id=\"和的作用\"><a class=\"anchor\" href=\"#和的作用\">#</a> #和 ## 的作用</h3>\n<blockquote>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// #利用宏参数字符串化</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name function\">ARGV</span><span class=\"token expression\"><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">)</span> <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span></span><span class=\"token string\">\"\"</span><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">x</span><span class=\"token string\">\" is %s\\n\"</span><span class=\"token expression\"><span class=\"token punctuation\">,</span>#x<span class=\"token punctuation\">)</span> </span><span class=\"token comment\">// 表示把参数 x 解释为字符串</span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">ARGV</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//a is a</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\">// ## 运算符粘合剂 组合成一个变量，强制分隔</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name function\">targ</span><span class=\"token expression\"><span class=\"token punctuation\">(</span> n <span class=\"token punctuation\">)</span>   X</span><span class=\"token punctuation\">##</span><span class=\"token expression\">n   </span><span class=\"token comment\">// 表示 X1...... 或 Xn</span></span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>   <span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>   <span class=\"token comment\">// ARGV(a);</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>   <span class=\"token keyword\">int</span> <span class=\"token function\">targ</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// 表示 X1 =10</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>   <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span>\"<span class=\"token operator\">%</span>d\\\"<span class=\"token punctuation\">,</span>X1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">//10</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>   <span class=\"token keyword\">return</span> <span class=\"token number\">0</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></blockquote>\n",
            "tags": [
                "嵌入式面试八股文",
                "嵌入式面试八股文"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2024/03/14/lanqiao/LED%E6%A8%A1%E5%9D%97/",
            "url": "https://littlestory1.github.io/2024/03/14/lanqiao/LED%E6%A8%A1%E5%9D%97/",
            "title": "LED模块",
            "date_published": "2024-03-14T12:58:15.000Z",
            "content_html": "<p>首先先来了解 LED 模块原理图：</p>\n<p><img data-src=\"image-20240314210251591.png\" alt=\"image-20240314210251591\"></p>\n<p>如图所示，8 个 led 和引脚之间有着一个锁存器，</p>\n<p>了解锁存器作用：</p>\n<p>理解成开关加存储器的结合体更为贴切，当锁存器使能时，可以用于数据交换；交换后的数据就被关起来了，暂时无法更改，直到下一次锁存器使能进行数据交换。</p>\n<p>PD2 引脚为控制锁存器引脚，当 PD2 输出高电平时，锁存器解锁，反之上锁。</p>\n<p>由图可知，LED 拥有公共的 VDD，而为了让二极管导通，PCx 引脚需要输出低电平（即 0）</p>\n<p>由锁存器的知识可知，PD2 引脚需要是有效电平，才能让 PCx 引脚工作，如图可得，PD2 需要输出高电平（即 1）</p>\n<p>CUBEMX 配置：</p>\n<p>GPIO 配置：</p>\n<p>将所用到的 GPIO 设成输出模式</p>\n<p><img data-src=\"image-20240314212415776.png\" alt=\"image-20240314212415776\"></p>\n<p>RCC 配置：</p>\n<p><img data-src=\"image-20240314212608698.png\" alt=\"image-20240314212608698\"></p>\n<p>时钟树配置：</p>\n<p>这里采用内部时钟：</p>\n<p><img data-src=\"image-20240314212637343.png\" alt></p>\n<p>led.c:</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">LED_Control</span><span class=\"token punctuation\">(</span>u8 led_ctrl<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>\t<span class=\"token comment\">// 先熄灭所有 LED 灯</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\">//\tHAL_GPIO_WritePin (GPIOC,GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);\t// 让 PC8~PC15 输出高电平，熄灭 LED</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>\t<span class=\"token function\">HAL_GPIO_WritePin</span><span class=\"token punctuation\">(</span>GPIOC<span class=\"token punctuation\">,</span><span class=\"token number\">0xff00</span><span class=\"token punctuation\">,</span>GPIO_PIN_SET<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\t\t<span class=\"token comment\">// 让 PC8~PC15 输出高电平，熄灭 LED</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>\t<span class=\"token function\">HAL_GPIO_WritePin</span><span class=\"token punctuation\">(</span>GPIOD<span class=\"token punctuation\">,</span>GPIO_PIN_2<span class=\"token punctuation\">,</span>GPIO_PIN_SET<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\t<span class=\"token comment\">// 打开锁存器</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>\t<span class=\"token function\">HAL_GPIO_WritePin</span><span class=\"token punctuation\">(</span>GPIOD<span class=\"token punctuation\">,</span>GPIO_PIN_2<span class=\"token punctuation\">,</span>GPIO_PIN_RESET<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\t<span class=\"token comment\">// 关闭锁存器</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\">// 根据 led_ctrl 来点亮对应的 LED</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token function\">HAL_GPIO_WritePin</span><span class=\"token punctuation\">(</span>GPIOC<span class=\"token punctuation\">,</span>led_ctrl<span class=\"token operator\">&lt;&lt;</span><span class=\"token number\">8</span><span class=\"token punctuation\">,</span>GPIO_PIN_RESET<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// 根据 led_ctrl 输出低电平，点亮 LED</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token function\">HAL_GPIO_WritePin</span><span class=\"token punctuation\">(</span>GPIOD<span class=\"token punctuation\">,</span>GPIO_PIN_2<span class=\"token punctuation\">,</span>GPIO_PIN_SET<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\t<span class=\"token comment\">// 打开锁存器</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token function\">HAL_GPIO_WritePin</span><span class=\"token punctuation\">(</span>GPIOD<span class=\"token punctuation\">,</span>GPIO_PIN_2<span class=\"token punctuation\">,</span>GPIO_PIN_RESET<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\t<span class=\"token comment\">// 关闭锁存器</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure>",
            "tags": [
                "蓝桥杯嵌入式",
                "蓝桥杯嵌入式"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2024/02/29/stm32/stm32%E2%80%94TIM%E5%AE%9A%E6%97%B6%E4%B8%AD%E6%96%AD/",
            "url": "https://littlestory1.github.io/2024/02/29/stm32/stm32%E2%80%94TIM%E5%AE%9A%E6%97%B6%E4%B8%AD%E6%96%AD/",
            "title": "stm32—TIM定时中断",
            "date_published": "2024-02-28T19:19:04.000Z",
            "content_html": "<p>假期摆了几个月，一点没学（摆子是这样的），还有两天开学，打算这两天尽可能的把 stm32 标准库的内容给补完上传到博客，肝就完了。</p>\n<h2 id=\"一-tim简介\"><a class=\"anchor\" href=\"#一-tim简介\">#</a> 一、TIM 简介</h2>\n<ul>\n<li>TIM（Timer）定时器</li>\n<li>定时器可以对输入的时钟进行计数，并在计数值达到设定值时触发中断</li>\n<li>16 位计数器、预分频器、自动重装寄存器的时基单元，在 72MHz 计数时钟下可以实现最大 59.65s 的定时</li>\n<li>不仅具备基本的定时中断功能，而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能</li>\n<li>根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型</li>\n</ul>\n<h2 id=\"二-定时器类型\"><a class=\"anchor\" href=\"#二-定时器类型\">#</a> 二、定时器类型</h2>\n<table>\n<thead>\n<tr>\n<th>类型</th>\n<th>编号</th>\n<th>总线</th>\n<th>功能</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>高级定时器</td>\n<td>TIM1、TIM8</td>\n<td>APB2</td>\n<td>拥有通用定时器全部功能，并额外具有重复计数器、死区生成、互补输出、刹车输入等功能</td>\n</tr>\n<tr>\n<td>通用定时器</td>\n<td>TIM2、TIM3、TIM4、TIM5</td>\n<td>APB1</td>\n<td>拥有基本定时器的全部功能、并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能</td>\n</tr>\n<tr>\n<td>基本定时器</td>\n<td>TIM6、TIM7</td>\n<td>APB1</td>\n<td>拥有定时中断、主模式触发 DAC 的功能</td>\n</tr>\n</tbody>\n</table>\n<p>1、基本定时器</p>\n<p><img data-src=\"image-20240513205136172.png\" alt=\"image-20240513205136172\"></p>\n<blockquote>\n<p><strong>预分频器</strong></p>\n<p>若预分频器 PSC 寄存器写 0，就是不分频或叫作 1 分频，输出频率 = 输入频率 / 1=72MHz；</p>\n<p>若寄存器写 1，就是 2 分频，输出频率 = 输入频率 / 2=36MHz；</p>\n<p>若寄存器写 2，就是 3 分频，输出频率 = 输入频率 / 3=24MHz……</p>\n<p>实际分频系数 = 预分频器的值 + 1</p>\n<p>该预分频器为 16 位，所以最大值为 65535，也就是 65536 分频</p>\n</blockquote>\n<blockquote>\n<p><strong>计数器</strong></p>\n<p>计数器可以对预分频后的计数时钟进行计数，计数时钟每来一个上升沿，计数器的值 + 1，该预分频器为 16 位，所以值可以从 0 加到 65535，再加便回到 0 重新开始。</p>\n<p>所以计数器的值在计时过程中不断自增运行，当自增运行到目标值时，产生中断，那就完成了定时的任务。</p>\n<p>所以还需要一个存储目标值的寄存器，即自动重装寄存器。</p>\n</blockquote>\n<blockquote>\n<p><strong>自动重装寄存器</strong></p>\n<p>自动重装寄存器也是 16 位，存储我们需要的计数目标。</p>\n<p>计数值 = 自动重装寄存器 产生的中断叫做 “<strong>更新中断</strong>”，通往 NVIC，再配置好 NVIC 的定时器通道，那么定时器的更新中断就能得到 CPU 的响应了。</p>\n<p>“<strong>更新事件</strong>” 不会触发中断，但可以触发内部其他电路的工作</p>\n</blockquote>\n<p>2、通用定时器</p>\n<p>通用定时器框图：</p>\n<p><img data-src=\"image-20240515022319373.png\" alt=\"image-20240515022319373\"></p>\n<p>基本定时器仅支持向上计数模式，通用定时器和高级定时器支持<strong>向上计数</strong>、<strong>向下计数</strong>和<strong>中央对齐计数</strong>三种模式，常用向上计数模式。</p>\n<p>3、高级定时器</p>\n<p><img data-src=\"image-20240515022427412.png\" alt=\"image-20240515022427412\"></p>\n<p>高级定时器多一个重复计数器，当时基单元发生 update 事件时，重复计数器 + 1 计数</p>\n<h2 id=\"三-定时中断基本结构\"><a class=\"anchor\" href=\"#三-定时中断基本结构\">#</a> 三、定时中断基本结构</h2>\n<p><img data-src=\"image-20240515022624954.png\" alt=\"image-20240515022624954\"></p>\n<h2 id=\"四-定时器中断程序实例\"><a class=\"anchor\" href=\"#四-定时器中断程序实例\">#</a> 四、定时器中断程序实例：</h2>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">\"stm32f10x.h\"</span>                  <span class=\"token comment\">// Device header</span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre> </pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">Timer_Init</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>\t<span class=\"token comment\">//①开启时钟，选择时钟源</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>\t<span class=\"token function\">RCC_APB1PeriphClockCmd</span><span class=\"token punctuation\">(</span>RCC_APB1Periph_TIM2<span class=\"token punctuation\">,</span>ENABLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>\t<span class=\"token function\">TIM_InternalClockConfig</span><span class=\"token punctuation\">(</span>TIM2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>\t<span class=\"token comment\">//②时基单元初始化</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>\tTIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>\tTIM_TimeBaseInitStructure<span class=\"token punctuation\">.</span>TIM_ClockDivision <span class=\"token operator\">=</span> TIM_CKD_DIV1<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>\tTIM_TimeBaseInitStructure<span class=\"token punctuation\">.</span>TIM_CounterMode <span class=\"token operator\">=</span> TIM_CounterMode_Up<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>\tTIM_TimeBaseInitStructure<span class=\"token punctuation\">.</span>TIM_Period <span class=\"token operator\">=</span> <span class=\"token number\">10000</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\t<span class=\"token comment\">//ARR 自动重装寄存器的值</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>\tTIM_TimeBaseInitStructure<span class=\"token punctuation\">.</span>TIM_Prescaler <span class=\"token operator\">=</span> <span class=\"token number\">7200</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\t\t<span class=\"token comment\">//PSC</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>\tTIM_TimeBaseInitStructure<span class=\"token punctuation\">.</span>TIM_RepetitionCounter <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\t<span class=\"token comment\">// 重复计数器</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>\t<span class=\"token function\">TIM_TimeBaseInit</span><span class=\"token punctuation\">(</span>TIM2<span class=\"token punctuation\">,</span><span class=\"token operator\">&amp;</span>TIM_TimeBaseInitStructure<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>\t<span class=\"token comment\">//③使能更新中断</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>\t<span class=\"token function\">TIM_ClearFlag</span><span class=\"token punctuation\">(</span>TIM2<span class=\"token punctuation\">,</span>TIM_FLAG_Update<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\t<span class=\"token comment\">// 清除更新中断标志位</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>\t<span class=\"token function\">TIM_ITConfig</span><span class=\"token punctuation\">(</span>TIM2<span class=\"token punctuation\">,</span>TIM_IT_Update<span class=\"token punctuation\">,</span>ENABLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>\t<span class=\"token comment\">//④配置 NVIC</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>\t<span class=\"token function\">NVIC_PriorityGroupConfig</span> <span class=\"token punctuation\">(</span>NVIC_PriorityGroup_2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>\tNVIC_InitTypeDef NVIC_InitStructure<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>\tNVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannel <span class=\"token operator\">=</span> TIM2_IRQn<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>\tNVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannelCmd <span class=\"token operator\">=</span> ENABLE<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>\tNVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannelPreemptionPriority <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>\tNVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannelSubPriority <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>\t<span class=\"token function\">NVIC_Init</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>NVIC_InitStructure<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>\t<span class=\"token comment\">//⑤启动定时器</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>\t<span class=\"token function\">TIM_Cmd</span><span class=\"token punctuation\">(</span>TIM2<span class=\"token punctuation\">,</span>ENABLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre> </pre></td></tr><tr><td data-num=\"31\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">TIM2_IRQHandler</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">TIM_GetITStatus</span><span class=\"token punctuation\">(</span>TIM2<span class=\"token punctuation\">,</span>TIM_IT_Update<span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> SET<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>\t<span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>\t\t</pre></td></tr><tr><td data-num=\"36\"></td><td><pre>\t\t<span class=\"token function\">TIM_ClearFlag</span><span class=\"token punctuation\">(</span>TIM2<span class=\"token punctuation\">,</span>TIM_FLAG_Update<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>\t<span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure>",
            "tags": [
                "stm32单片机",
                "stm32"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2023/12/26/note/%E5%AD%A6%E6%9C%9F%E7%BB%93%E6%9D%9F/",
            "url": "https://littlestory1.github.io/2023/12/26/note/%E5%AD%A6%E6%9C%9F%E7%BB%93%E6%9D%9F/",
            "title": "学期结束",
            "date_published": "2023-12-26T11:20:54.000Z",
            "content_html": "<p>一转眼，又过去了一学期，这学期可以说还是很颓废，什么都没学到没干成。许多计划一拖再拖，直到学期结束都没有开始实施，很难受，深感自己太懒了。而我的朋友以及找到实习了，看来我也得加油了。下学期的蓝桥杯冲一下省一，这几天先看看校内的物联网比赛能不能想出些作品，原本计划的基于旭日 x3 派的跟随小车估计不太行，近期一直在做这个，但一直没有进展下面大概说下吧：</p>\n<p>首先是网络的问题，一开始下载了官方的 2.0 的镜像，配置好网络后，经常出现没网的问题或者 ssh 连不上，很是头疼，网上许多方法都尝试过，依旧不行，也试过重装镜像，还是这样。最后是安装了最新 2.1 版本的镜像解决的。流汗黄豆</p>\n<p>然后就是在官方 tros 的问题，一开始我是根据论坛的教程来的，但每次 apt install hhp 都会出问题一直提示没找到该包，试过更换下载源，问题更多了，很是难绷，后来发现，是官方的 tros 已经更新到 tros2 了，不再叫 hhp，但官方论坛上大多都是上一年的帖子，所以白折腾了半天时间。后面在调用摄像头的时候，也是许多问题，官方资料信息滞后，然后各种包的更新又是经常删改，而资料也不更新，这点还是在看更新日志发现的，更死的是论坛基本没人，这时我便体会到小众板子的缺点，始终还得是树莓派。我现在也放弃这个了，全部交给朋友尝试了。我则准备 planB。</p>\n<p>总结这学期学得一坨，希望下学期好好加油吧</p>\n<p>下面放几张回家路上的蓝天：</p>\n<p><img data-src=\"%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20231226192414.jpg\" alt></p>\n<p><img data-src=\"%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20231226192443.jpg\" alt=\"微信图片_20231226192443\"></p>\n",
            "tags": [
                "杂谈",
                "杂谈"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2023/12/04/stm32/%E7%BA%A2%E5%A4%96%E6%B5%8B%E6%AC%A1/",
            "url": "https://littlestory1.github.io/2023/12/04/stm32/%E7%BA%A2%E5%A4%96%E6%B5%8B%E6%AC%A1/",
            "title": "红外计次",
            "date_published": "2023-12-04T13:12:03.000Z",
            "content_html": "<p><strong>连线图：</strong></p>\n<p><img data-src=\"image-20231204211750143.png\" alt=\"image-20231204211750143\"></p>\n<p>DO -&gt; B14</p>\n<p>在正确连接通电后，可以看到红外传感器亮起，当挡光片在槽位中时，开关指示灯灭。</p>\n<p>代码编写思路分析：</p>\n<p>我们先看回 EXTI 基本结构：</p>\n<p><img data-src=\"image-20231204214112102.png\" alt=\"image-20231204214112102\"></p>\n<p>我们需要使用到 GPIOB，AFIO，EXTI</p>\n<p>在使用之前，我们得先开时钟，其中 EXTI 不需要开启时钟：</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">RCC_APB2PeriphClockCmd</span><span class=\"token punctuation\">(</span>RCC_APB2Periph_GPIOB<span class=\"token punctuation\">,</span>ENABLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">RCC_APB2PeriphClockCmd</span><span class=\"token punctuation\">(</span>RCC_APB2Periph_AFIO<span class=\"token punctuation\">,</span>ENABLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>这样我们就开启了 GPIOB，AFIO 的时钟了，然后就是引脚的初始化了：</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//GPIOB 引脚初始化</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>GPIO_InitTypeDef GPIO_InitStructure<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">// 指定 Pin14 为上拉输入模式（内部连接上拉电阻，悬空时默认高电平）</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>GPIO_InitStructure<span class=\"token punctuation\">.</span>GPIO_Mode<span class=\"token operator\">=</span> GPIO_Mode_IPU<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>GPIO_InitStructure<span class=\"token punctuation\">.</span>GPIO_Pin<span class=\"token operator\">=</span> GPIO_Pin_14<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>GPIO_InitStructure<span class=\"token punctuation\">.</span>GPIO_Speed<span class=\"token operator\">=</span> GPIO_Speed_50MHz<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token function\">GPIO_Init</span><span class=\"token punctuation\">(</span>GPIOB<span class=\"token punctuation\">,</span><span class=\"token operator\">&amp;</span>GPIO_InitStructure<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>接着就是配置 AFIO 外设了，在此之前，先来介绍几个 AFIO 的库函数：</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 复位 AFIO 外设，清除 AFIO 外设配置</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">GPIO_AFIODeInit</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\">// 锁定 GPIO 配置，参数指定某个引脚，锁定该引脚配置，防止意外更改</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">GPIO_PinLockConfig</span><span class=\"token punctuation\">(</span>GPIO_TypeDef<span class=\"token operator\">*</span> GPIOx<span class=\"token punctuation\">,</span> <span class=\"token class-name\">uint16_t</span> GPIO_Pin<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\">// 配置 AFIO 的事件输出功能</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">GPIO_EventOutputConfig</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint8_t</span> GPIO_PortSource<span class=\"token punctuation\">,</span> <span class=\"token class-name\">uint8_t</span> GPIO_PinSource<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">GPIO_EventOutputCmd</span><span class=\"token punctuation\">(</span>FunctionalState NewState<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\">// 用来进行引脚重映射，参数一为重映射方式，参数二为新的状态</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">GPIO_PinRemapConfig</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span> GPIO_Remap<span class=\"token punctuation\">,</span> FunctionalState NewState<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token comment\">// 配置 AFIO 的数据选择器，来选择中断引脚，也是本次所需要用到的函数</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">GPIO_EXTILineConfig</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint8_t</span> GPIO_PortSource<span class=\"token punctuation\">,</span> <span class=\"token class-name\">uint8_t</span> GPIO_PinSource<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token comment\">// 官方库函数及其解释</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token comment\">/**</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>  * @brief  Selects the GPIO pin used as EXTI Line.</pre></td></tr><tr><td data-num=\"19\"></td><td><pre>  * @param  GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines.</pre></td></tr><tr><td data-num=\"20\"></td><td><pre>  *   This parameter can be GPIO_PortSourceGPIOx where x can be (A..G).</pre></td></tr><tr><td data-num=\"21\"></td><td><pre>  * @param  GPIO_PinSource: specifies the EXTI line to be configured.</pre></td></tr><tr><td data-num=\"22\"></td><td><pre>  *   This parameter can be GPIO_PinSourcex where x can be (0..15).</pre></td></tr><tr><td data-num=\"23\"></td><td><pre>  * @retval None</pre></td></tr><tr><td data-num=\"24\"></td><td><pre>  */</pre></td></tr><tr><td data-num=\"25\"></td><td><pre></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">GPIO_EXTILineConfig</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint8_t</span> GPIO_PortSource<span class=\"token punctuation\">,</span> <span class=\"token class-name\">uint8_t</span> GPIO_PinSource<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>  <span class=\"token class-name\">uint32_t</span> tmp <span class=\"token operator\">=</span> <span class=\"token number\">0x00</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>  <span class=\"token comment\">/* Check the parameters */</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>  <span class=\"token function\">assert_param</span><span class=\"token punctuation\">(</span><span class=\"token function\">IS_GPIO_EXTI_PORT_SOURCE</span><span class=\"token punctuation\">(</span>GPIO_PortSource<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>  <span class=\"token function\">assert_param</span><span class=\"token punctuation\">(</span><span class=\"token function\">IS_GPIO_PIN_SOURCE</span><span class=\"token punctuation\">(</span>GPIO_PinSource<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>  </pre></td></tr><tr><td data-num=\"33\"></td><td><pre>  tmp <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span><span class=\"token punctuation\">)</span><span class=\"token number\">0x0F</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;&lt;</span> <span class=\"token punctuation\">(</span><span class=\"token number\">0x04</span> <span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span>GPIO_PinSource <span class=\"token operator\">&amp;</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">uint8_t</span><span class=\"token punctuation\">)</span><span class=\"token number\">0x03</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>  AFIO<span class=\"token operator\">-></span>EXTICR<span class=\"token punctuation\">[</span>GPIO_PinSource <span class=\"token operator\">>></span> <span class=\"token number\">0x02</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">&amp;=</span> <span class=\"token operator\">~</span>tmp<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>  AFIO<span class=\"token operator\">-></span>EXTICR<span class=\"token punctuation\">[</span>GPIO_PinSource <span class=\"token operator\">>></span> <span class=\"token number\">0x02</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">|=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span><span class=\"token punctuation\">)</span>GPIO_PortSource<span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;&lt;</span> <span class=\"token punctuation\">(</span><span class=\"token number\">0x04</span> <span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span>GPIO_PinSource <span class=\"token operator\">&amp;</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">uint8_t</span><span class=\"token punctuation\">)</span><span class=\"token number\">0x03</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p><strong>配置 AFIO 外设</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 选择 GPIOB 作为外部中断源，指定 Pin14 为外部中断线</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">GPIO_EXTILineConfig</span><span class=\"token punctuation\">(</span>GPIO_PortSourceGPIOB<span class=\"token punctuation\">,</span>GPIO_PinSource14<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>配置完 AFIO 后，PB14 引脚的电平信号就可以顺利通过 AFIO，进入到 EXTI 电路了</p>\n<p>接下来，就是配置 EXTI 了，老样子，我们先了解一下 EXTI 的库函数</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 清除 EXTI 配置，恢复上电默认状态</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">EXTI_DeInit</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\">// 调用这个函数，就可以根据结构体参数里的参数配置 EXTI 外设</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">EXTI_Init</span><span class=\"token punctuation\">(</span>EXTI_InitTypeDef<span class=\"token operator\">*</span> EXTI_InitStruct<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\">// 可以把参数传递的结构体变量赋一个默认值</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">EXTI_StructInit</span><span class=\"token punctuation\">(</span>EXTI_InitTypeDef<span class=\"token operator\">*</span> EXTI_InitStruct<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\">// 用于软件触发外部中断的</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">EXTI_GenerateSWInterrupt</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span> EXTI_Line<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token comment\">// 可以获取指定的标志位是否被置 1 了</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>FlagStatus <span class=\"token function\">EXTI_GetFlagStatus</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span> EXTI_Line<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token comment\">// 可以对置 1 的标志位进行清除</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">EXTI_ClearFlag</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span> EXTI_Line<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token comment\">// 获取中断标志位是否被置 1 了</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>ITStatus <span class=\"token function\">EXTI_GetITStatus</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span> EXTI_Line<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token comment\">// 清除中断挂起标志位</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">EXTI_ClearITPendingBit</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span> EXTI_Line<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p><strong>配置 EXTI</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>EXTI_InitTypeDef EXTI_InitStructure<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// 指定配置中断线</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>EXTI_InitStructure<span class=\"token punctuation\">.</span>EXTI_Line <span class=\"token operator\">=</span> EXTI_Line14<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\">// 开启中断</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>EXTI_InitStructure<span class=\"token punctuation\">.</span>EXTI_LineCmd<span class=\"token operator\">=</span> ENABLE<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\">// 指定外部中断线模式为中断模式</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>EXTI_InitStructure<span class=\"token punctuation\">.</span>EXTI_Mode<span class=\"token operator\">=</span> EXTI_Mode_Interrupt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\">// 选择为下降沿触发</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>EXTI_InitStructure<span class=\"token punctuation\">.</span>EXTI_Trigger<span class=\"token operator\">=</span> EXTI_Trigger_Falling<span class=\"token punctuation\">;</span>\t</pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token function\">EXTI_Init</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>EXTI_InitStructure<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>这样 EXTI 就配置完成了，PB14 的电平信号就可以通过 EXTI 通向下一级 NVIC 了，接下来就是配置 NVIC 了</p>\n<p>先了解一下库函数；</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 用于指定中断分组</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">NVIC_PriorityGroupConfig</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span> NVIC_PriorityGroup<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">// 根据结构体里面的参数初始化 NVIC</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">NVIC_Init</span><span class=\"token punctuation\">(</span>NVIC_InitTypeDef<span class=\"token operator\">*</span> NVIC_InitStruct<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\">// 设置中断向量表</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">NVIC_SetVectorTable</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span> NVIC_VectTab<span class=\"token punctuation\">,</span> <span class=\"token class-name\">uint32_t</span> Offset<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\">// 系统低功耗配置</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">NVIC_SystemLPConfig</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint8_t</span> LowPowerMode<span class=\"token punctuation\">,</span> FunctionalState NewState<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token comment\">//</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">SysTick_CLKSourceConfig</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">uint32_t</span> SysTick_CLKSource<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p><strong>配置 NVIC</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//\t选择第二个分组，响应 2，抢占 2</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">NVIC_PriorityGroupConfig</span><span class=\"token punctuation\">(</span>NVIC_PriorityGroup_2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>NVIC_InitTypeDef NVIC_InitStructure<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\">// 选择 EXTI10-15 通道</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>NVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannel<span class=\"token operator\">=</span> EXTI15_10_IRQn<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\">// 选择使能</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>NVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannelCmd<span class=\"token operator\">=</span> ENABLE<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token comment\">// 设定抢占优先级</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>NVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannelPreemptionPriority<span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\">// 设定响应优先级</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>NVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannelSubPriority<span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token function\">NVIC_Init</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>NVIC_InitStructure<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p><strong>中断函数的编写</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 中断函数</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">EXTI15_10_IRQHandler</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token comment\">// 判断中断线路 14 标志位是否被置 1</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">EXTI_GetITStatus</span><span class=\"token punctuation\">(</span>EXTI_Line14<span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> SET<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>\t<span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>\t\tCountSensor_Count<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>\t\t<span class=\"token function\">EXTI_ClearITPendingBit</span><span class=\"token punctuation\">(</span>EXTI_Line14<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>\t<span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p><strong>所有代码展示：</strong></p>\n<p><strong>main.c</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">\"stm32f10x.h\"</span>                  <span class=\"token comment\">// Device header</span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">\"OLED.h\"</span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">\"CountSensor.h\"</span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>\t<span class=\"token function\">OLED_Init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>\t<span class=\"token function\">CountSensor_Init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>\t</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>\t<span class=\"token function\">OLED_ShowString</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token string\">\"Count:\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>\t<span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>\t<span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>\t\t<span class=\"token function\">OLED_ShowNum</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">7</span><span class=\"token punctuation\">,</span><span class=\"token function\">CountSensor_Get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>\t\t</pre></td></tr><tr><td data-num=\"14\"></td><td><pre>\t<span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p><strong>CountSensor.h</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">ifndef</span> <span class=\"token expression\">__COUNT_SENSOR_H</span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">__COUNT_SENSOR_H</span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">CountSensor_Init</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token class-name\">uint16_t</span> <span class=\"token function\">CountSensor_Get</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">endif</span></span></pre></td></tr></table></figure><p><strong>CountSensor.c</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">\"stm32f10x.h\"</span>                  <span class=\"token comment\">// Device header</span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token class-name\">uint16_t</span> CountSensor_Count<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">CountSensor_Init</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>\t<span class=\"token function\">RCC_APB2PeriphClockCmd</span><span class=\"token punctuation\">(</span>RCC_APB2Periph_GPIOB<span class=\"token punctuation\">,</span>ENABLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>\t<span class=\"token function\">RCC_APB2PeriphClockCmd</span><span class=\"token punctuation\">(</span>RCC_APB2Periph_AFIO<span class=\"token punctuation\">,</span>ENABLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>\tGPIO_InitTypeDef GPIO_InitStructure<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>\tGPIO_InitStructure<span class=\"token punctuation\">.</span>GPIO_Mode<span class=\"token operator\">=</span> GPIO_Mode_IPU<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>\tGPIO_InitStructure<span class=\"token punctuation\">.</span>GPIO_Pin<span class=\"token operator\">=</span> GPIO_Pin_14<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>\tGPIO_InitStructure<span class=\"token punctuation\">.</span>GPIO_Speed<span class=\"token operator\">=</span> GPIO_Speed_50MHz<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>\t<span class=\"token function\">GPIO_Init</span><span class=\"token punctuation\">(</span>GPIOB<span class=\"token punctuation\">,</span><span class=\"token operator\">&amp;</span>GPIO_InitStructure<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>\t</pre></td></tr><tr><td data-num=\"16\"></td><td><pre>\t<span class=\"token function\">GPIO_EXTILineConfig</span><span class=\"token punctuation\">(</span>GPIO_PortSourceGPIOB<span class=\"token punctuation\">,</span>GPIO_PinSource14<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>\tEXTI_InitTypeDef EXTI_InitStructure<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>\tEXTI_InitStructure<span class=\"token punctuation\">.</span>EXTI_Line <span class=\"token operator\">=</span> EXTI_Line14<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>\tEXTI_InitStructure<span class=\"token punctuation\">.</span>EXTI_LineCmd<span class=\"token operator\">=</span> ENABLE<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>\tEXTI_InitStructure<span class=\"token punctuation\">.</span>EXTI_Mode<span class=\"token operator\">=</span> EXTI_Mode_Interrupt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>\tEXTI_InitStructure<span class=\"token punctuation\">.</span>EXTI_Trigger<span class=\"token operator\">=</span> EXTI_Trigger_Falling<span class=\"token punctuation\">;</span>\t</pre></td></tr><tr><td data-num=\"23\"></td><td><pre>\t<span class=\"token function\">EXTI_Init</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>EXTI_InitStructure<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>\t</pre></td></tr><tr><td data-num=\"25\"></td><td><pre>\t<span class=\"token function\">NVIC_PriorityGroupConfig</span><span class=\"token punctuation\">(</span>NVIC_PriorityGroup_2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>\tNVIC_InitTypeDef NVIC_InitStructure<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>\tNVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannel<span class=\"token operator\">=</span> EXTI15_10_IRQn<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>\tNVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannelCmd<span class=\"token operator\">=</span> ENABLE<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>\tNVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannelPreemptionPriority<span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>\tNVIC_InitStructure<span class=\"token punctuation\">.</span>NVIC_IRQChannelSubPriority<span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>\t<span class=\"token function\">NVIC_Init</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>NVIC_InitStructure<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre></pre></td></tr><tr><td data-num=\"35\"></td><td><pre><span class=\"token class-name\">uint16_t</span> <span class=\"token function\">CountSensor_Get</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>\t<span class=\"token keyword\">return</span> CountSensor_Count<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre></pre></td></tr><tr><td data-num=\"40\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">EXTI15_10_IRQHandler</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre>\t<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">EXTI_GetITStatus</span><span class=\"token punctuation\">(</span>EXTI_Line14<span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> SET<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre>\t<span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"44\"></td><td><pre>\t\tCountSensor_Count<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"45\"></td><td><pre>\t\t<span class=\"token function\">EXTI_ClearITPendingBit</span><span class=\"token punctuation\">(</span>EXTI_Line14<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"46\"></td><td><pre>\t<span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"47\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>效果：</p>\n<p><img data-src=\"image-20231204223747017.png\" alt=\"image-20231204223747017\"></p>\n",
            "tags": [
                "stm32单片机",
                "stm32"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2023/11/28/stm32/stm32-%E4%B8%AD%E6%96%AD%E7%B3%BB%E7%BB%9F/",
            "url": "https://littlestory1.github.io/2023/11/28/stm32/stm32-%E4%B8%AD%E6%96%AD%E7%B3%BB%E7%BB%9F/",
            "title": "stm32-中断系统",
            "date_published": "2023-11-28T12:24:47.000Z",
            "content_html": "<h1 id=\"中断系统\"><a class=\"anchor\" href=\"#中断系统\">#</a> 中断系统</h1>\n<ul>\n<li>中断：在主程序运行过程中，出现了特定的中断触发条件（中断源），使得 cpu 暂停当前正在运行的程序，转而去处理中断程序，处理完成后又返回原来被暂停的位置继续运行</li>\n<li>中断优先级：当有多个中断源同时申请中断时，cpu 会根据中断源的轻重缓急进行判决，优先相应更加紧急的中断源</li>\n<li>中断嵌套：当一个中断程序正在运行时，又有新的更高优先级的中断源申请中断，cpu 再次暂停当前中断程序，转而去处理新的中断程序，处理完成后依次返回</li>\n</ul>\n<h2 id=\"中断执行流程\"><a class=\"anchor\" href=\"#中断执行流程\">#</a> 中断执行流程</h2>\n<p><img data-src=\"image-20231128203106761.png\" alt=\"image-20231128203106761\"></p>\n<h1 id=\"stm32中断\"><a class=\"anchor\" href=\"#stm32中断\">#</a> stm32 中断</h1>\n<p>68 个可屏蔽中断同道，包含 EXTI、TIM、ADC、USART、SPI、I2C、RTC 等多个外设</p>\n<p>使用 NVIC 统一管理中断，每个中断通道都拥有 16 个可编程的优先等级，可对优先级进行分组，进一步设置抢占优先级和响应优先级</p>\n<h2 id=\"nvic\"><a class=\"anchor\" href=\"#nvic\">#</a> NVIC</h2>\n<h3 id=\"nvic基本结构\"><a class=\"anchor\" href=\"#nvic基本结构\">#</a> NVIC 基本结构</h3>\n<p><img data-src=\"image-20231201161530501.png\" alt=\"image-20231201161530501\"></p>\n<p>NVIC：嵌套中断向量控制器，在 stm32 中，它是用来统一分配中断优先级和管理中断的。NVIC 是一个内核外设。</p>\n<p>NVIC 只有一个输出口，NVIC 根据每个中断的优先级分配中断的先后顺序之后通过右边的一个输出口告诉 cpu 该执行哪个中断</p>\n<p>打个比喻，NVIC 相当于医院里的叫号系统，cpu 相当于医生，NVIC 将中断进行排序并依次单个进入 cpu 执行。</p>\n<h3 id=\"nvic优先级分组\"><a class=\"anchor\" href=\"#nvic优先级分组\">#</a> NVIC 优先级分组</h3>\n<ul>\n<li>NVIC 的中断优先级由优先级寄存器的四位（0~15）决定，这 4 位可以进行切分，分为高 n 位的抢占优先级和低 4-n 位的响应优先级</li>\n<li>抢占优先级高的可以中断嵌套，响应优先级高的可以优先排队，抢占优先级和响应优先级均相同的按中断号排队</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>分组方式</th>\n<th>抢占优先级</th>\n<th>响应优先级</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>分组 0</td>\n<td>0 位，取值为 0</td>\n<td>4 位，取值为 0~15</td>\n</tr>\n<tr>\n<td>分组 1</td>\n<td>1 位，取值为 0~1</td>\n<td>3 位，取值为 0~7</td>\n</tr>\n<tr>\n<td>分组 2</td>\n<td>2 位，取值为 0~3</td>\n<td>2 位，取值为 0~3</td>\n</tr>\n<tr>\n<td>分组 3</td>\n<td>3 位，取值为 0~7</td>\n<td>1 位，取值为 0~1</td>\n</tr>\n<tr>\n<td>分组 4</td>\n<td>4 位，取值为 0~15</td>\n<td>0 位，取值为 0</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"exti\"><a class=\"anchor\" href=\"#exti\">#</a> EXTI</h2>\n<h3 id=\"exti简介\"><a class=\"anchor\" href=\"#exti简介\">#</a> EXTI 简介</h3>\n<ul>\n<li>EXTI（Extern Interrupt）外部中断</li>\n<li>EXTI 可以监测指定 GPIO 口的电平信号，当其指定的 GPIO 口产生电平变化时，EXTI 将立即向 NVIC 发出中断申请，经过 NVIC 裁决后即可中断 CPU 主程序，使 CPU 执行 EXTI 对应的中断程序</li>\n<li>支持的触发方式：</li>\n</ul>\n<ol>\n<li>​\t上升沿：电平从低电平变到高电平的瞬间触发中断</li>\n<li>​\t下降沿：电平从高电平变到低电平的瞬间触发中断</li>\n<li>​\t双边沿：上升沿和下降沿都可以触发中断</li>\n<li>​\t软件触发：引脚无变化，程序里执行一句代码，就能触发中断</li>\n</ol>\n<ul>\n<li>\n<p>支持的 GPIO 口：所有 GPIO 口，但相同的 Pin 不能同时触发中断</p>\n</li>\n<li>\n<p>同道数：16 个 GPIO_Pin，外加 PVD 输出，RTC 闹钟，USB 唤醒，以太网唤醒</p>\n</li>\n<li>\n<p>触发响应方式：中断响应 / 事件响应</p>\n</li>\n</ul>\n<p>总结：中断响应是正常的流程，引脚电平变化触发中断，事件响应不会触发中断，而是触发别的外设操作，属于外设之间的联合工作</p>\n<h3 id=\"exti基本结构\"><a class=\"anchor\" href=\"#exti基本结构\">#</a> EXTI 基本结构</h3>\n<p><img data-src=\"image-20231201164947649.png\" alt=\"image-20231201164947649\"></p>\n",
            "tags": [
                "stm32单片机",
                "stm32"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2023/11/24/stm32/stm32-GPIO/",
            "url": "https://littlestory1.github.io/2023/11/24/stm32/stm32-GPIO/",
            "title": "stm32(GPIO)",
            "date_published": "2023-11-24T12:57:49.000Z",
            "content_html": "<h4 id=\"首先我们先来学习如何开时钟\"><a class=\"anchor\" href=\"#首先我们先来学习如何开时钟\">#</a> <strong>首先我们先来学习如何开时钟：</strong></h4>\n<h5 id=\"1为什么需要开时钟\"><a class=\"anchor\" href=\"#1为什么需要开时钟\">#</a> <strong>1：为什么需要开时钟？</strong></h5>\n<p>我们可以通俗的理解时钟是外设电路的心脏，不打开时钟就无法使用。每个外设都有独立时钟，如果不打开时钟外设就不能用，原因就是为了低功耗节省用电，不用的外设可以不打开时钟</p>\n<h5 id=\"2如何开启对应时钟\"><a class=\"anchor\" href=\"#2如何开启对应时钟\">#</a> <strong>2：如何开启对应时钟？</strong></h5>\n<p>首先，我们需要看芯片对应的外设总线架构图</p>\n<p><img data-src=\"%E6%80%BB%E7%BA%BF%E6%9E%B6%E6%9E%84.jpg\" alt=\"总线架构\"></p>\n<p>假设我们现在需要开 GPIOA 的时钟，我们可以看到 GPIOA 是在 APB2 外设总线上的，那么开启 GPIOA 时钟代码如下：</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">RCC_APB2PeriphClockCmd</span><span class=\"token punctuation\">(</span>RCC_APB2Periph_GPIOA<span class=\"token punctuation\">,</span> ENABLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>关闭时钟代码如下：</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">RCC_APB2PeriphClockCmd</span><span class=\"token punctuation\">(</span>RCC_APB2Periph_GPIOA<span class=\"token punctuation\">,</span> DISENABLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h4 id=\"一-gpio是什么\"><a class=\"anchor\" href=\"#一-gpio是什么\">#</a> 一、GPIO 是什么？</h4>\n<p>GPIO 全称 General Purpose Input Output 即通用输入 / 输出，其实 GPIO 的本质就是芯片的一个引脚，通常在 ARM 中所有的 I/O 都是通用的。不过由于每个开发板上都会设计不同的外围电路，这就造成 GPIO 的功能可能有所不同，大部分 GPIO 都是有复用功能的，比如有些 GPIO 可能是串口的 TX 或 RX，也可能是 I2C 的 SCL 或 SDA 线。</p>\n<p>所以我们不仅要知道 GPIO 能够输出高低电平，还要理解为什么有些 GPIO 可以复用某些功能，而其他的不可以。</p>\n<h4 id=\"二-gpio内部结构\"><a class=\"anchor\" href=\"#二-gpio内部结构\">#</a> 二、GPIO 内部结构</h4>\n<p><img data-src=\"GPIO%E7%BB%93%E6%9E%84%E5%9B%BE.jpg\" alt=\"GPIO结构图\"></p>\n<h5 id=\"我们首先分析上面的结构电路\"><a class=\"anchor\" href=\"#我们首先分析上面的结构电路\">#</a> <strong>我们首先分析上面的结构电路：</strong></h5>\n<p><strong>1、保护二极管</strong>： 保护二极管从它的名字就不难想到他是用来对系统进行保护的，通过两个二极管的导通可以防止引脚外部输入电压过低或过高。当电压过高时，上方的保护二极管导通。当电压过低时，下方的二极管导通，防止不正常电压导入到芯片内部造成芯片烧毁。</p>\n<p><strong>2、P・MOS 管和 N・MOS 管</strong>： GPIO 经过两个二极管的保护后向上流入输入模式，向下流入输出模式，而输出模式的控制是由一个由 P・MOS 管和 N・MOS 管组成的单元电路，该电路主要是控制输出的模式，由该结构狗策划给你的单元电路具有推挽输出和开漏输出两种模式。</p>\n<p><strong>当系统配置为推挽输出模式时：</strong></p>\n<ul>\n<li>\n<p>若向该结构中输入高电平，经过反向后，上方的 P-MOS 导通，下方的 N-MOS 关闭，对外输出高电平；</p>\n</li>\n<li>\n<p>若向该结构中输入低电平时，经过反向后，下方的 N-MOS 管导通，上方的 P-MOS 关闭，对外输出低电平。</p>\n</li>\n<li>\n<p>当引脚高低电平切换时，两个 MOS 管轮流导通，P 管负责灌电流，N 管负责拉电流，使其负载能力和开关速度都比普通的方式有很大的提高。推挽输出的低电平为 0V，高电平为 3.3V。</p>\n</li>\n</ul>\n<p><strong>当系统配置为开漏输出模式时：</strong></p>\n<ul>\n<li>\n<p>上方的 P-MOS 管完全不工作；</p>\n</li>\n<li>\n<p>如果我们控制输出为 0，低电平，则 P-MOS 管关闭，N-MOS 管导通，使输出接地；</p>\n</li>\n<li>\n<p>若控制输出为 1（它无法直接输出高电平）时，则 P-MOS 管和 N-MOS 管都关闭，所以开漏输出模式下引脚既不输出高电平，也不输出低电平，为高阻态。</p>\n</li>\n</ul>\n<p><strong>推挽输出模式</strong>一般应用在输出电平为 0 和 3.3V 而且需要高速切换开关状态的场合。</p>\n<p><strong>开漏输出模式</strong>一般应用在 I2C、SMBUS 通信等需要 线与功能的总线电路中。</p>\n<p><strong>在单片机中除了必须用开漏模式的场合，一般习惯使用推挽输出模式</strong></p>\n<p><strong>3、输出数据寄存器</strong>：前面我们知道双了 MOS 管结构电路的输入信号，是由 GPIO 输出数据寄存器 GPIOx_ODR 提供的，因此我们可以通过修改输出数据寄存器的值，就可以修改 GPIO 引脚的输出电平。而置位 / 复位寄存器 GPIOx_BSRR 可以通过修改输出数据寄存器的值，从而影响电路的输出。</p>\n<p><strong>4、复用功能输出</strong>：复用功能输出中的复用是指 STM32 的其他片上外设对 GPIO 引脚进行控制，此时 GPIO 引脚用作该外设功能的一部分，算是第二用途。从其他外设引出来的复用功能输出信号与 GPIO 本身的数据寄存器都连接到双 MOS 管结构的输入中。</p>\n<h4 id=\"三-输入输出模式\"><a class=\"anchor\" href=\"#三-输入输出模式\">#</a> 三、输入输出模式</h4>\n<h5 id=\"gpio八种模式\"><a class=\"anchor\" href=\"#gpio八种模式\">#</a> <strong>GPIO 八种模式</strong></h5>\n<table>\n<thead>\n<tr>\n<th><strong>模式</strong></th>\n<th></th>\n<th><strong>介绍</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>浮空输入</td>\n<td>GPIO_Mode_IN_FLOATING</td>\n<td>若引脚悬空，则电平不确定</td>\n</tr>\n<tr>\n<td>上拉输入</td>\n<td>GPIO_Mode_IPU</td>\n<td>内部连接上拉电阻，悬空时默认高电平</td>\n</tr>\n<tr>\n<td>下拉输入</td>\n<td>GPIO_Mode_IPD</td>\n<td>内部连接下拉电阻，悬空时默认低电平</td>\n</tr>\n<tr>\n<td>模拟输入</td>\n<td>GPIO_Mode_AIN</td>\n<td>GPIO 无效，引脚直接接入内部 ADC</td>\n</tr>\n<tr>\n<td>开漏输出</td>\n<td>GPIO_Mode_Out_OD</td>\n<td>高电平为高阻态，低电平接 VSS（负极）</td>\n</tr>\n<tr>\n<td>推挽输出</td>\n<td>GPIO_Mode_Out_PP</td>\n<td>高电平接 VDD，低电平接 VSS</td>\n</tr>\n<tr>\n<td>复用开漏输出</td>\n<td>GPIO_Mode_AF_OD</td>\n<td>由片上外设控制，高电平为高阻态，低电平接 VSS</td>\n</tr>\n<tr>\n<td>复用推挽输出</td>\n<td>GPIO_Mode_AF_PP</td>\n<td>由片上外设控制，高电平接 VDD，低电平接 VSS</td>\n</tr>\n</tbody>\n</table>\n<h5 id=\"浮空输入\"><a class=\"anchor\" href=\"#浮空输入\">#</a> 浮空输入</h5>\n<p>浮空输入模式下， <code>I/O</code>  端口的电平信号直接进入输入数据寄存器。也就是说，I/O 的电平状态是不确定的，完全由外部输入决定；如果在该引脚悬空（在无信号输入）的情况下，读取该端口的电平是不确定的，通常用于 <code>IIC</code> 、 <code>USART</code>  等总线设备上。</p>\n<p><img data-src=\"image-20231125013402022.png\" alt=\"image-20231125013402022\"></p>\n<h5 id=\"上拉输入模式\"><a class=\"anchor\" href=\"#上拉输入模式\">#</a> 上拉输入模式</h5>\n<p>上拉输入模式下， <code>I/O</code>  端口的电平信号直接进入输入数据寄存器。但是在 <code>I/O</code>  端口悬空（在无信号输入）的情况下，输入端的电平保持在高电平（并且在 <code>I/O</code>  端口输入为低电平的时候，输入端的电平也是低电平）</p>\n<p><img data-src=\"image-20231125013449506.png\" alt=\"image-20231125013449506\"></p>\n<h5 id=\"下拉输入模式\"><a class=\"anchor\" href=\"#下拉输入模式\">#</a> 下拉输入模式</h5>\n<p>下拉输入模式下， <code>I/O</code>  端口的电平信号直接进入输入数据寄存器。但是在 <code>I/O</code>  端口悬空（在无信号输入）的情况下，输入端的电平保持在低电平；并且在 I/O 端口输入为高电平的时候，输入端的电平也是高电平。</p>\n<p><img data-src=\"image-20231125013542238.png\" alt=\"image-20231125013542238\"></p>\n<h5 id=\"模拟输入模式\"><a class=\"anchor\" href=\"#模拟输入模式\">#</a> 模拟输入模式</h5>\n<p>模拟输入模式下， <code>I/O</code>  端口的模拟信号（电压信号，而非电平信号）直接模拟输入到片上外设模块，比如 <code>ADC</code>  模块等。</p>\n<p><img data-src=\"image-20231125013643774.png\" alt=\"image-20231125013643774\"></p>\n<h5 id=\"开漏输出模式\"><a class=\"anchor\" href=\"#开漏输出模式\">#</a> 开漏输出模式</h5>\n<p>当系统配置为开漏输出模式时：</p>\n<ul>\n<li>\n<p>上方的 P-MOS 管完全不工作；</p>\n</li>\n<li>\n<p>如果我们控制输出为 0，低电平，则 P-MOS 管关闭，N-MOS 管导通，使输出接地；</p>\n</li>\n<li>\n<p>若控制输出为 1（它无法直接输出高电平）时，则 P-MOS 管和 N-MOS 管都关闭，所以开漏输出模式下引脚既不输出高电平，也不输出低电平，为高阻态。</p>\n</li>\n</ul>\n<h5 id=\"开漏复用输出模式\"><a class=\"anchor\" href=\"#开漏复用输出模式\">#</a> 开漏复用输出模式</h5>\n<p>开漏复用输出模式，与开漏输出模式很是类似。只是输出的高低电平的来源，不是让 CPU 直接写输出数据寄存器，取而代之利用片上外设模块的复用功能输出来决定的，一般用于片内外设功能： <code>TX1，MOSI，MISO，SCK，SS</code></p>\n<h5 id=\"推挽输出模式\"><a class=\"anchor\" href=\"#推挽输出模式\">#</a> 推挽输出模式</h5>\n<p>当系统配置为推挽输出模式时：</p>\n<ul>\n<li>\n<p>若向该结构中输入高电平，经过反向后，上方的 P-MOS 导通，下方的 N-MOS 关闭，对外输出高电平；</p>\n</li>\n<li>\n<p>若向该结构中输入低电平时，经过反向后，下方的 N-MOS 管导通，上方的 P-MOS 关闭，对外输出低电平。</p>\n</li>\n<li>\n<p>当引脚高低电平切换时，两个 MOS 管轮流导通，P 管负责灌电流，N 管负责拉电流，使其负载能力和开关速度都比普通的方式有很大的提高。推挽输出的低电平为 0V，高电平为 3.3V。</p>\n</li>\n</ul>\n<h5 id=\"推挽复用输出模式\"><a class=\"anchor\" href=\"#推挽复用输出模式\">#</a> 推挽复用输出模式</h5>\n<p>推挽复用输出模式，与推挽输出模式很是类似。只是输出的高低电平的来源，不是让 CPU 直接写输出数据寄存器，而是利用片上外设模块的复用功能输出来决定的，常见采用推挽输出模式的一般为片内外设功能 <code>IIC</code>  的 <code>SCL</code> 、 <code>SDL</code> 。</p>\n<p><img data-src=\"image-20231125014016489.png\" alt=\"image-20231125014016489\"></p>\n<h4 id=\"四-开漏输出和推挽输出的区别\"><a class=\"anchor\" href=\"#四-开漏输出和推挽输出的区别\">#</a> 四、开漏输出和推挽输出的区别</h4>\n<p>开漏输出和推挽输出模式的区别主要是开漏输出<strong>只可以输出强低电平，高电平得靠外部电阻拉高</strong>。输出端相当于三极管的集电极，适合于做电流型的驱动，其吸收电流的能力相对强 (一般 20ma 以内)；推挽输出<strong>可以输出强高、低电平</strong>，连接数字器件。</p>\n<table>\n<thead>\n<tr>\n<th></th>\n<th>推挽输出</th>\n<th>开漏输出</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>高电平驱动能力</td>\n<td>强</td>\n<td>由外部上拉电阻提供</td>\n</tr>\n<tr>\n<td>低电平驱动能力</td>\n<td>强</td>\n<td>强</td>\n</tr>\n<tr>\n<td>电平跳变速度</td>\n<td>快</td>\n<td>由外部上拉电阻决定，电阻越小，反应越快，功耗越大</td>\n</tr>\n<tr>\n<td>线与功能</td>\n<td>不支持</td>\n<td>支持</td>\n</tr>\n<tr>\n<td>电平转换</td>\n<td>不支持</td>\n<td>支持</td>\n</tr>\n</tbody>\n</table>\n<h4 id=\"五-stm32中gpio的配置\"><a class=\"anchor\" href=\"#五-stm32中gpio的配置\">#</a> 五、STM32 中 GPIO 的配置</h4>\n<p>初始化 GPIO 的常用格式是：</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>GPIO_InitTypeDef GPIO_InitStructure<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>GPIO_InitStructure<span class=\"token punctuation\">.</span>GPIO_Pin <span class=\"token operator\">=</span> GPIO_Pin_5<span class=\"token punctuation\">;</span> <span class=\"token comment\">//LED0-- PB.5 端口配置</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>GPIO_InitStructure<span class=\"token punctuation\">.</span>GPIO_Mode <span class=\"token operator\">=</span> GPIO_Mode_Out_PP<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 推挽输出</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>GPIO_InitStructure<span class=\"token punctuation\">.</span>GPIO_Speed <span class=\"token operator\">=</span> GPIO_Speed_50MHz<span class=\"token punctuation\">;</span><span class=\"token comment\">// 速度 50MHz</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token function\">GPIO_Init</span><span class=\"token punctuation\">(</span>GPIOB<span class=\"token punctuation\">,</span> GPIO_InitStructure<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// 根据设定参数配置 GPIO</span></pre></td></tr></table></figure><p><code>IO</code>  口速度设置有三个可选值：</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">typedef</span> <span class=\"token keyword\">enum</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>GPIO_Speed_10MHz<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>GPIO_Speed_2MHz<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>GPIO_Speed_50MHz</pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">&#125;</span>GPIOSpeed_TypeDef<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>模式则有 8 个可选定义如下：</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">typedef</span> <span class=\"token keyword\">enum</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#123;</span> GPIO_Mode_AIN <span class=\"token operator\">=</span> <span class=\"token number\">0x0</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 模拟输入</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>GPIO_Mode_IN_FLOATING <span class=\"token operator\">=</span> <span class=\"token number\">0x04</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 浮空输入</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>GPIO_Mode_IPD <span class=\"token operator\">=</span> <span class=\"token number\">0x28</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 下拉输入</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>GPIO_Mode_IPU <span class=\"token operator\">=</span> <span class=\"token number\">0x48</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 上拉输入</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>GPIO_Mode_Out_OD <span class=\"token operator\">=</span> <span class=\"token number\">0x14</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 开漏输出</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>GPIO_Mode_Out_PP <span class=\"token operator\">=</span> <span class=\"token number\">0x10</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 通用推挽输出</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>GPIO_Mode_AF_OD <span class=\"token operator\">=</span> <span class=\"token number\">0x1C</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 复用开漏输出</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>GPIO_Mode_AF_PP <span class=\"token operator\">=</span> <span class=\"token number\">0x18</span> <span class=\"token comment\">// 复用推挽</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token punctuation\">&#125;</span>GPIOMode_TypeDef<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p><strong>名词解释：</strong></p>\n<p>高阻态：是一个数字电路里常见的术语，指的是电路的一种输出状态，既不是高电平也不是低电平，如果高阻态再输入下一级电路的话，对下级电路无任何影响，和没接一样，如果用万用表测的话有可能是高电平也有可能是低电平，随它后面接的东西定的。电路分析时高阻态可做开路理解。你可以把它看作输出（输入）电阻非常大。它的极限状态可以认为悬空（开路）。也就是说理论上高阻态不是悬空，它是对地或对电源电阻极大的状态。而实际应用上与引脚的悬空几乎是一样的。</p>\n",
            "tags": [
                "stm32单片机",
                "stm32"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2023/11/21/stm32/stm32%EF%BC%88%E5%89%8D%E8%A8%80%EF%BC%89/",
            "url": "https://littlestory1.github.io/2023/11/21/stm32/stm32%EF%BC%88%E5%89%8D%E8%A8%80%EF%BC%89/",
            "title": "stm32前言",
            "date_published": "2023-11-21T14:38:11.000Z",
            "content_html": "<p><strong>前言</strong></p>\n<p>主要用于记录 stm32 的知识点以及学习过程，这样慢慢积累下来，会有莫名的成就感</p>\n<p>如果有误，欢迎加我 qq 指出错误</p>\n<p><strong>使用板子：</strong></p>\n<p>stm32f103c8t6 最小系统板</p>\n<p><strong>stm32 三种开发方式的区别</strong></p>\n<ul>\n<li><strong>寄存器模式</strong>：最底层的开发，运行速度最快。实际上也是使用了固件库，但是不是使用固件库的函数，而是使用了固件库的定义，包括宏定义，结构体定义。和 51 的开发差不多，但因为 32 的寄存器太多，实际开发手动配置大量寄存器极其耗费时间，同时在没有注释的情况下可读性差，所以较少使用。</li>\n<li><strong>标准库模式</strong>：基于寄存器进行了函数的封装，而由于函数封装以及内部大量的检查参数有效性的代码，运行速度相对于寄存器模式较慢。封装之后可以根据函数名字就能明白代码作用，容易记忆，使用方便，所以较多人使用。</li>\n<li><strong>HAL 库模式</strong>：全称是 Hardware Abstraction Layer（抽象印象层），相比于标准库更加深入的封装，有句柄、回调函数等概念，因此相对于标准库模式有更好的可移植性（可在不同芯片的移植），但代价就是更多的性能损失。</li>\n</ul>\n<p><strong>本系列采用标准库模式</strong></p>\n",
            "tags": [
                "stm32单片机",
                "stm32"
            ]
        },
        {
            "id": "https://littlestory1.github.io/2023/11/21/note/%E7%AC%AC%E4%B8%80%E7%AF%87%E5%8D%9A%E5%AE%A2/",
            "url": "https://littlestory1.github.io/2023/11/21/note/%E7%AC%AC%E4%B8%80%E7%AF%87%E5%8D%9A%E5%AE%A2/",
            "title": "第一篇博客",
            "date_published": "2023-11-21T14:23:55.000Z",
            "content_html": "<p>觉得原本的博客主题过于花里胡哨，于是换了个主题，然后把全部文章删了，重新整理，重新写</p>\n",
            "tags": [
                "杂谈",
                "杂谈"
            ]
        }
    ]
}