<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tony Bai &#187; 解引用</title>
	<atom:link href="http://tonybai.com/tag/%e8%a7%a3%e5%bc%95%e7%94%a8/feed/" rel="self" type="application/rss+xml" />
	<link>https://tonybai.com</link>
	<description>一个程序员的心路历程</description>
	<lastBuildDate>Mon, 08 Jun 2026 23:32:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>“Go is badly designed”？它像极了我们当年恨过的物理老师！</title>
		<link>https://tonybai.com/2025/04/17/go-is-badly-designed/</link>
		<comments>https://tonybai.com/2025/04/17/go-is-badly-designed/#comments</comments>
		<pubDate>Thu, 17 Apr 2025 13:30:56 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[catch]]></category>
		<category><![CDATA[error-handling]]></category>
		<category><![CDATA[GC]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[goroutine]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[nil]]></category>
		<category><![CDATA[panic]]></category>
		<category><![CDATA[Pointer]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[range]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[simplicity]]></category>
		<category><![CDATA[Slice]]></category>
		<category><![CDATA[try]]></category>
		<category><![CDATA[try-catch]]></category>
		<category><![CDATA[哲学]]></category>
		<category><![CDATA[垃圾回收]]></category>
		<category><![CDATA[安全]]></category>
		<category><![CDATA[开发效率]]></category>
		<category><![CDATA[性能]]></category>
		<category><![CDATA[指针]]></category>
		<category><![CDATA[接口]]></category>
		<category><![CDATA[空指针]]></category>
		<category><![CDATA[简洁]]></category>
		<category><![CDATA[维护]]></category>
		<category><![CDATA[编译]]></category>
		<category><![CDATA[解引用]]></category>
		<category><![CDATA[语言设计]]></category>
		<category><![CDATA[速度]]></category>
		<category><![CDATA[错误处理]]></category>
		<category><![CDATA[隐喻]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=4583</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/04/17/go-is-badly-designed 大家好，我是Tony Bai。 今天刷X (前Twitter) 的时候，看到Golang Insiders社区下面这条推文，真是差点扑哧一声笑出来，感觉说得太形象了，必须分享给大家： 这位叫Lyes的开发者回应 “Go is badly designed” (Go 语言设计得很糟糕) 的说法，他打了个比方： 这让我想起了我的高中物理老师，我们当时都恨他，因为他从不‘放水’简化物理知识。课难、考试难，大部分人在他手下分数都不高，所以他自然成了‘坏老师’。 Go 语言就有点像他。它从不‘放水’，直面问题。你可以很快用它变得高效，写出远比用 Python 或 JavaScript 写得更好的软件。 但你也得知道，这门语言不会‘溺爱’你。当你的服务器因为一个 nil map 或其他新手常犯的错误而 panic 时，别生气。 不像 Rust，Go 的编译器不会在你编程生涯的每一刻都‘牵着你的手’。它会给你足够的方向让你知道该往哪走，满足你 80% 的需求，同时仍然保持你的生产力。 怎么样？看完这段话，是不是像极了我们初学Go时，被nil pointer dereference 或 index out of range 当头棒喝的瞬间？ 像极了我们当年一边抱怨物理老师太严格、考试太变态，一边又不得不硬着头皮去啃那些公式和定理的样子？ Lyes 的这个比喻，可以说精准地戳中了 Go 语言的一些核心特质，也解释了为什么关于“Go是否设计糟糕”的争论从未停止。咱们今天就借着这个“物理老师”的比喻，好好聊聊Go的“坏脾气”和它背后的设计哲学。 那个从不“放水”的“严格老师” Lyes 说 Go 不会 “dumb [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/go-is-badly-designed-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/04/17/go-is-badly-designed">本文永久链接</a> &#8211; https://tonybai.com/2025/04/17/go-is-badly-designed</p>
<p>大家好，我是Tony Bai。</p>
<p>今天刷X (前Twitter) 的时候，看到<a href="https://x.com/i/communities/1685641800449462272">Golang Insiders社区</a>下面这条推文，真是差点扑哧一声笑出来，感觉说得太形象了，必须分享给大家：</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-is-badly-designed-2.png" alt="" /></p>
<p>这位叫Lyes的开发者回应 “Go is badly designed” (Go 语言设计得很糟糕) 的说法，他打了个比方：</p>
<blockquote>
<p>这让我想起了我的高中物理老师，我们当时都恨他，因为他从不‘放水’简化物理知识。课难、考试难，大部分人在他手下分数都不高，所以他自然成了‘坏老师’。</p>
<p>Go 语言就有点像他。它从不‘放水’，直面问题。你可以很快用它变得高效，写出远比用 Python 或 JavaScript 写得更好的软件。</p>
<p>但你也得知道，这门语言不会‘溺爱’你。当你的服务器因为一个 nil map 或其他新手常犯的错误而 panic 时，别生气。</p>
<p>不像 Rust，Go 的编译器不会在你编程生涯的每一刻都‘牵着你的手’。它会给你足够的方向让你知道该往哪走，满足你 80% 的需求，同时仍然保持你的生产力。</p>
</blockquote>
<p>怎么样？看完这段话，<strong>是不是像极了我们初学Go时，被nil pointer dereference 或 index out of range 当头棒喝的瞬间？</strong> 像极了我们当年一边抱怨物理老师太严格、考试太变态，一边又不得不硬着头皮去啃那些公式和定理的样子？</p>
<p>Lyes 的这个比喻，可以说精准地戳中了 Go 语言的一些核心特质，也解释了为什么关于“Go是否设计糟糕”的争论从未停止。咱们今天就借着这个“物理老师”的比喻，好好聊聊Go的“坏脾气”和它背后的设计哲学。</p>
<h2>那个从不“放水”的“严格老师”</h2>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-is-badly-designed-3.png" alt="" /></p>
<p>Lyes 说 Go 不会 “dumb down anything(简化任何事物，去除复杂性)”，这太对了。Go语言的设计哲学里，<strong>“简洁”（Simplicity）</strong> 是核心原则之一，但这不代表“简单化”到隐藏问题的程度。相反，它选择<strong>直面问题</strong>：</p>
<ul>
<li>
<p><strong>显式的错误处理 (if err != nil)</strong>：不像某些语言用try-catch将错误“藏”起来，Go强迫你几乎在每次可能出错的操作后都检查错误。这很“烦”，但它逼着你思考每一步潜在的风险，就像物理老师逼着你弄懂每个公式的推导过程。</p>
</li>
<li>
<p><strong>直白的运行时Panic</strong>：当你对一个 nil 的 map 或 slice 进行操作时，Go 不会帮你“优雅地”处理，而是直接给你一个运行时 panic，程序崩溃。这很“粗暴”，但它用最直接的方式告诉你：“同学，你这里犯了个基础错误，赶紧改！” 这不就是物理老师发现你基本概念没搞懂时，直接点名批评，让你印象深刻吗？</p>
</li>
<li>
<p><strong>没有“溺爱”的语法糖</strong>：相比一些现代语言，Go 的语法糖相对较少。它没有泛滥的操作符重载，没有复杂的<a href="https://tonybai.com/2021/12/02/go-has-implicit-type-convertion">隐式转换</a>。很多事情需要你明确地写出来。这让代码有时候显得“啰嗦”，但大大降低了阅读和理解他人代码时的歧义，保证了大规模团队协作的效率。就像物理老师坚持用标准的符号和单位，不允许自创“简写”，是为了保证科学的严谨性。</p>
</li>
</ul>
<h2>“坏老师”真的“坏”吗？—— 严格背后的价值</h2>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-is-badly-designed-4.png" alt="" /></p>
<p>我们当年可能都偷偷抱怨过物理老师不近人情，但多年后回想，是不是反而感谢他的严格，才让我们打下了坚实的基础？Go 语言的“严格”同样如此：</p>
<ol>
<li>
<p><strong>逼你养成好习惯</strong>：被 nil panic 搞崩溃几次后，你自然就学会了在使用 map/slice/pointer 前做检查，学会了初始化，学会了更严谨地思考边界条件。这种被“教训”出来的习惯，最终会融入你的编程血液，让你写出更健壮、更可靠的代码。这比那些“温柔”地帮你掩盖了问题，直到生产环境才爆发出更大危机的语言，是不是长期来看更负责任？</p>
</li>
<li>
<p><strong>简单直白，易于掌握核心</strong>：虽然会“当头棒喝”，但Go的核心概念相对较少，语法简洁。一旦你掌握了它的规则（比如错误处理模式、接口哲学、goroutine的使用），就能快速上手，并且写出的代码风格差异不会太大，易于团队维护。它不像某些语言，特性繁多，学习曲线陡峭，精通需要漫长时间。Go就像物理老师划定的核心考点，虽然难，但范围明确，努力就有回报。</p>
</li>
<li>
<p><strong>效率与务实：给你“80%的指引”</strong>：Lyes 提到了<a href="https://tonybai.com/2021/03/15/rust-vs-go-why-they-are-better-together">Go与Rust的对比</a>，说Go不会“全程牵手”。这正是<strong>Go的务实之处</strong>。它在编译速度、开发效率和运行时安全之间做了一个取舍。它通过快速编译、垃圾回收、简洁的并发模型，让你能高效地构建系统，满足大部分（比如 80%）场景的需求。它相信开发者是成年人，应该为自己的代码负责，而不是让编译器承担所有检查的重任。这就像物理老师教会你核心原理和解题方法，但不会一步步带着你做完所有练习题，他相信你能举一反三，独立解决问题。</p>
</li>
</ol>
<h2>不是“设计糟糕”，而是哲学不同</h2>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-is-badly-designed-5.png" alt="" /></p>
<p>所以，“Go is badly designed” 吗？</p>
<p>与其说是“糟糕”，不如说是<strong>设计哲学和目标受众的不同</strong>。</p>
<ul>
<li>如果你期望一门语言能像 Rust 那样，在编译期就为你消除几乎所有内存安全和并发风险，愿意为此付出更陡峭的学习曲线和更长的编译时间，那么 Go 可能确实“不够好”。</li>
<li>但如果你追求的是<strong>快速构建、高效部署、简单可靠、易于维护</strong>的大型后端系统，能接受在运行时处理一些本可避免的错误（并通过良好的实践和工具来减少它们），那么Go的设计哲学可能恰恰是它的<strong>优点</strong>。</li>
</ul>
<p>Go 就像那位严格的物理老师，他可能不会让你在学习过程中时刻感到“舒适”，甚至会让你经历挫败和“阵痛”。但他目标明确，方法直接，逼着你打好基础，养成严谨的习惯，最终让你能够独立、高效地解决实际问题。</p>
<p><strong>那么，你怎么看？</strong></p>
<ul>
<li>你觉得Go语言像不像你当年“恨过”的某位老师？</li>
<li>你第一次遇到 nil panic 时是什么感受？是觉得Go设计糟糕，还是反思自己代码的问题？</li>
<li>你更喜欢 Go 这种“给你方向，但不全程牵手”的方式，还是 Rust 那种“无微不至的保护”？</li>
</ul>
<p><strong>欢迎在评论区留下你的看法，分享你和 Go “相爱相杀”的故事！</strong></p>
<hr />
<p><strong>原「Gopher部落」已重装升级为「Go &amp; AI 精进营」知识星球，快来加入星球，开启你的技术跃迁之旅吧！</strong></p>
<p>我们致力于打造一个高品质的 <strong>Go 语言深度学习</strong> 与 <strong>AI 应用探索</strong> 平台。在这里，你将获得：</p>
<ul>
<li><strong>体系化 Go 核心进阶内容:</strong> 深入「Go原理课」、「Go进阶课」、「Go避坑课」等独家深度专栏，夯实你的 Go 内功。</li>
<li><strong>前沿 Go+AI 实战赋能:</strong> 紧跟时代步伐，学习「Go+AI应用实战」、「Agent开发实战课」，掌握 AI 时代新技能。</li>
<li><strong>星主 Tony Bai 亲自答疑:</strong> 遇到难题？星主第一时间为你深度解析，扫清学习障碍。</li>
<li><strong>高活跃 Gopher 交流圈:</strong> 与众多优秀 Gopher 分享心得、讨论技术，碰撞思想火花。</li>
<li><strong>独家资源与内容首发:</strong> 技术文章、课程更新、精选资源，第一时间触达。</li>
</ul>
<p>衷心希望「Go &amp; AI 精进营」能成为你学习、进步、交流的港湾。让我们在此相聚，享受技术精进的快乐！欢迎你的加入！</p>
<p><img src="http://image.tonybai.com/img/tonybai/gopher-and-ai-tribe-zsxq-small-card.jpg" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/go-programming-from-beginner-to-master-qr.png" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/go-first-course-banner.png" alt="img{512x368}" /></p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格6$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>Gopher Daily(Gopher每日新闻) &#8211; https://gopherdaily.tonybai.com</p>
<p>我的联系方式：</p>
<ul>
<li>微博(暂不可用)：https://weibo.com/bigwhite20xx</li>
<li>微博2：https://weibo.com/u/6484441286</li>
<li>博客：tonybai.com</li>
<li>github: https://github.com/bigwhite</li>
<li>Gopher Daily归档 &#8211; https://github.com/bigwhite/gopherdaily</li>
<li>Gopher Daily Feed订阅 &#8211; https://gopherdaily.tonybai.com/feed</li>
</ul>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/04/17/go-is-badly-designed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>简析多级指针解引用</title>
		<link>https://tonybai.com/2013/03/23/multi-dimension-pointer-in-c/</link>
		<comments>https://tonybai.com/2013/03/23/multi-dimension-pointer-in-c/#comments</comments>
		<pubDate>Sat, 23 Mar 2013 02:38:18 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Blogger]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[dereference]]></category>
		<category><![CDATA[Pointer]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[博客]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[思考]]></category>
		<category><![CDATA[指针]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[解引用]]></category>
		<category><![CDATA[语法]]></category>

		<guid isPermaLink="false">http://tonybai.com/?p=1227</guid>
		<description><![CDATA[指针是C语言中公认的最为强大的语法要素，但同时也是最难理解的语法要素，它曾给程序员带来了无数麻烦和痛苦，以致于在C语言之后诞生的很多新兴 语言中我们再也难觅指针的身影了。 下面是一个最简单的C语言指针的例子： int a = 5; int *p = &#38;a; 其中p就是一个指针变量。如果C语言中仅仅存在这类指针，那显然指针不会形成&#8220;大患&#8221;。经常地我们会在代码中看到下面的情形： int **q = &#38;p; int ***z = &#38;q; 随着符号&#39;*&#39;个数的增加，C代码的理解复杂度似乎也曾指数级别增长似的。像q、z这样的指向指针的指针(pointer to pointer to &#8230;)变量，中文俗称&#8220;多级指针&#8221;。不过在一些正式的英文C语言教程中，我没能找到其正式的英文说法。在老外的这些书 中，它们多被称为pointer to pointer (to pointer to &#8230;.)。多级指针的确是很难理解的，特别当与函数、数组等联合在一起使用时。今天在写代码时恰好撞见了多级指针，于是就打算在这里说说对多级指针以及 其解引用的一些粗浅理解。 指针究竟是啥？ 和普通变量想比，指针变量到底有何不同，究竟何为指针(变量)？我们来看一个例子： int a = 5; int *p = &#38;a; printf(&#34;a addr = [%p]\n&#34;, &#38;a); printf(&#34;a content = [%d]\n&#34;, a); printf(&#34;p addr [...]]]></description>
			<content:encoded><![CDATA[<p>指针是<a href="http://en.wikipedia.org/wiki/C_(programming_language)">C语言</a>中公认的最为强大的语法要素，但同时也是最难理解的语法要素，它曾给程序员带来了无数麻烦和痛苦，以致于在C语言之后诞生的很多新兴 语言中我们再也难觅指针的身影了。</p>
<p>下面是一个最简单的C语言指针的例子：<br />
	<span style="font-family:courier new,courier,monospace;">int a = 5;<br />
	int *p = &amp;a;</span></p>
<p>其中p就是一个指针变量。如果C语言中仅仅存在这类指针，那显然指针不会形成&ldquo;大患&rdquo;。经常地我们会在代码中看到下面的情形：</p>
<p><span style="font-family:courier new,courier,monospace;">int **q = &amp;p;<br />
	int ***z = &amp;q;</span></p>
<p>随着符号&#39;*&#39;个数的增加，C代码的理解复杂度似乎也曾指数级别增长似的。像q、z这样的指向指针的指针(pointer to pointer to &#8230;)变量，中文俗称&ldquo;<b>多级指针</b>&rdquo;。不过在一些正式的英文C语言教程中，我没能找到其正式的英文说法。在老外的这些书 中，它们多被称为pointer to pointer (to pointer to &#8230;.)。多级指针的确是很难理解的，特别当与函数、数组等联合在一起使用时。今天在写代码时恰好撞见了多级指针，于是就打算在这里说说对多级指针以及 其解引用的一些粗浅理解。</p>
<p><b>指针究竟是啥？</b></p>
<p>和普通变量想比，指针变量到底有何不同，究竟何为指针(变量)？我们来看一个例子：</p>
<p><span style="font-family:courier new,courier,monospace;">int a = 5;<br />
	int *p = &amp;a;</span></p>
<p>printf(&quot;a addr = [%p]\n&quot;, &amp;a);<br />
	printf(&quot;a content = [%d]\n&quot;, a);<br />
	printf(&quot;p addr = [%p]\n&quot;, &amp;p);<br />
	printf(&quot;p content = [%p]\n&quot;, p);<br />
	printf(&quot;*p = [%d]\n&quot;, *p);</p>
<p>*p = 6;<br />
	printf(&quot;after modify, *p = [%d]\n&quot;, *p);</p>
<p>编译这个小程序并执行，输出结果如下：</p>
<p><span style="font-family:courier new,courier,monospace;">a addr = [0xbfb609b8]<br />
	a content = [5]<br />
	p addr = [0xbfb609bc]<br />
	p content = [0xbfb609b8]<br />
	*p = [5]<br />
	after modify, *p = [6]</span></p>
<p>通过两个变量的addr，我们可以看到a、p两个变量都是在栈上分配的变量。不同的是普通整型变量a对应的内存单元(a content)中存储的值为整型值5，是一个数值；而变量p对应的内存单元(p content)中存储的值为0xbfb609b8，是变量a的地址，用栈变量简图可以表示如下：</p>
<p><span style="font-family:courier new,courier,monospace;">| &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
	|<u>0xbfb609b8</u>| &lt;- &amp;p [0xbfb609bc]<br />
	|5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | &lt;- &amp;a [<u>0xbfb609b8</u>]<br />
	| &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</span></p>
<p>可以看出指针变量的<b>第一个特点</b>是它是一种以存储其他变量地址为目的的变量。一个T类型的指针变量(一级指针)就是一个存储了某T类 型值变量的地址的内存单元。</p>
<p>例子中最后那个输出是对指针的解引用(dereference)操作，指针的解引用操作的结果是得到指针所指的地址上的变量的值。在这个例子中指 针所指到内存地址为0xbfb609b8，也就是a变量的位置，因此*p的结果为变量a的值，即5。因此我们得到指针变量的<b>第二个特点</b>： 通过对指针的解引用，我们可以获得其指向的内存单元所表示的值。</p>
<p>在例子中，我们看到了这行代码 *p = 6，并发现执行这行代码后，a变量的值变为了6。这就是指针的<b>第三个特点</b>：当解引用作左值时，它可以修改其所指内存地址上变量的值。a被修改后的栈变量分布简图：</p>
<p><span style="font-family:courier new,courier,monospace;">| &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
	|0xbfb609b8| &lt;- &amp;p [0xbfb609bc]<br />
	|6 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | &lt;- &amp;a [0xbfb609b8]<br />
	| &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</span></p>
<p><b>二级指针</b></p>
<p>我们再来分析一下下面的示例程序的输出结果。</p>
<p><span style="font-family:courier new,courier,monospace;">int a = 5;<br />
	int b = 13;<br />
	int *p = &amp;a;<br />
	printf(&quot;*p = %d\n&quot;, *p);&nbsp;<br />
	int **q = &amp;p;<br />
	(*q) = &amp;b;<br />
	printf(&quot;*p = %d\n&quot;, *p);</span></p>
<p>根据前面的分析，第一次*p输出时p指向a的地址，对p解引用的结果就是a所在内存单元的值，即5。接下来的代码分析起来就需要谨慎一些了。我们先来看看 int **q = &amp;p这行代码。根据对一级指针的分析，我们可以将int **q理解成(int*) *q，这样q指向的地址就是一个int*型的变量的内存地址，该地址上的值本身也是一个地址值。在这个例子中，(int*) *q = &amp;p; 也就是说q中存储的值就是变量p的地址。通过*q我们可以得到p中存储的地址值(&amp;a)；而若*q作为左值，显然就是修改p中存储的地址值喽，因 此(*q) = &amp;b则相当于p = &amp;b，则第二个*p的输出结果为变量b所在内存单元的值，即13。</p>
<p>在修改*q前，栈上内存布局：</p>
<p><span style="font-family:courier new,courier,monospace;">| &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
	|<u>0xbf830ec8</u>| &lt;- &amp;q [0xbf830ecc]<br />
	|0xbf830ec0| &lt;- &amp;p [<u>0xbf830ec8</u>]<br />
	|11 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | &lt;- &amp;b [0xbf830ec4]<br />
	|5 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | &lt;- &amp;a [0xbf830ec0]<br />
	| &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</span></p>
<p>在修改*q的值后，栈上内存布局：</p>
<p><span style="font-family:courier new,courier,monospace;">| &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
	|0xbf830ec8| &lt;- &amp;q [0xbf830ecc]<br />
	|<u>0xbf830ec4</u>| &lt;- &amp;p [0xbf830ec8] /* 通过*q修改 */<br />
	|11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | &lt;- &amp;b [<u>0xbf830ec4</u>]<br />
	|5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | &lt;- &amp;a [0xbf830ec0]<br />
	| &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</span></p>
<p>再来分析一下**q的值又是啥呢？有了前面的铺垫：*q &lt;=&gt; p，那**q &lt;=&gt; *(*q) &lt;=&gt; *p，其值自然就明了了，就是b的值。</p>
<p><b>多级指针</b></p>
<p>有了一级指针和二级指针的分析打基础，当我们遇到更多*的时候，只是遵循这个方法耐心分析就是了，比如：</p>
<p><span style="font-family:courier new,courier,monospace;">int a = 5;<br />
	int *p = &amp;a;<br />
	int **q = &amp;p;<br />
	int ***z = &amp;q;</span></p>
<p>我们可以对比着前面一、二级指针的理解方法来理解这三个指针p、q和z：<br />
	&nbsp;&nbsp;&nbsp; &#8211; 一级指针p自身存储的是整型值变量a的地址，对一级指针解引用(*p)得到的是值变量a的值；*p作左值，修改的是变量a的值；<br />
	&nbsp;&nbsp;&nbsp; &#8211; 二级指针q自身存储的是一级整型指针变量p的地址，对二级指针解引用(*q)得到的是一级指针p自身存储的值(a的地址:&amp;a)；*p作左值时，修改的一级指针p的指向；<br />
	&nbsp;&nbsp;&nbsp; &#8211; 三级指针z自身存储的是二级整型指针变量q的地址，对三级指针解引用(*z)得到的是二级指针q自身存储的值，也就是p的地址(&amp;p)；对*z再 解引用(**z)，相当于得到p自身存储的值，也就是a的地址&amp;a；对**z再解引用，即***z，相当于得到a自身存储的变量值，即5。用一个 等价式可以更形象的表达：***z &lt;=&gt; **(*z) &lt;=&gt; **q &lt;=&gt; *(*q) &lt;=&gt; *p &lt;=&gt; 5。<br />
	&nbsp;&nbsp;&nbsp; &#8211; 更高级别的指针可依次类推。不过如果再对***z解引用，即****z，那则相当于对整型数5（非地址）进行解引用，会出现编译错误： 一元 &lsquo;*&rsquo;参数类型无效(有&lsquo;int&rsquo;)。</p>
<p style='text-align:left'>&copy; 2013, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2013/03/23/multi-dimension-pointer-in-c/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
