-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.xml
6134 lines (5946 loc) · 807 KB
/
index.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>左岚の博客</title>
<link>https://zuoliangyu.github.io/</link>
<description>Recent content on 左岚の博客</description>
<generator>Hugo -- gohugo.io</generator>
<language>zh-cn</language>
<copyright>Example Person</copyright>
<lastBuildDate>Sat, 12 Oct 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://zuoliangyu.github.io/index.xml" rel="self" type="application/rss+xml" /><item>
<title>C语言入门基础</title>
<link>https://zuoliangyu.github.io/p/c%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E5%9F%BA%E7%A1%80/</link>
<pubDate>Sat, 12 Oct 2024 00:00:00 +0000</pubDate>
<guid>https://zuoliangyu.github.io/p/c%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E5%9F%BA%E7%A1%80/</guid>
<description><h1 id="第一部分c语言基础概念详解"><strong>第一部分:C语言基础概念详解</strong>
</h1><h2 id="1-c语言的起源与特点">1. <strong>C语言的起源与特点</strong>
</h2><p>C语言诞生于20世纪70年代初,最初用于开发UNIX操作系统。它的设计目标是使得代码更高效且能够直接操作硬件,因此C语言也被称为“低级语言的高级化”。以下是C语言的几个主要特点:</p>
<ul>
<li><strong>高效性</strong>:C语言编写的程序运行速度非常快,尤其适合底层开发,如操作系统、驱动程序等。</li>
<li><strong>可移植性</strong>:C语言代码具有良好的跨平台移植性,只需少量修改就可以在不同平台上编译运行。</li>
<li><strong>灵活性</strong>:C语言允许直接访问内存,可以进行精细的内存操作(如指针操作)。</li>
<li><strong>丰富的运算符</strong>:C语言提供了丰富的运算符集,能够进行各种类型的数据运算和逻辑运算。</li>
</ul>
<h2 id="2-程序的基本结构">2. <strong>程序的基本结构</strong>
</h2><p>每个C语言程序都由以下几个主要部分组成:</p>
<ul>
<li><strong>预处理指令</strong>:使用 <code>#include</code>来引入标准库,如 <code>stdio.h</code>,为输入输出提供函数。</li>
<li><strong>主函数 <code>main()</code></strong>:每个C程序的入口点是 <code>main()</code>函数,程序的执行从 <code>main()</code>开始。其返回类型通常是 <code>int</code>,表示程序的执行状态(<code>0</code>通常表示成功)。</li>
</ul>
<p>一个简单的C语言程序如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Hello, World!</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="3-变量和数据类型">3. <strong>变量和数据类型</strong>
</h2><p>C语言是一种<strong>静态类型语言</strong>,这意味着在使用变量之前,必须声明变量的类型。主要的数据类型有:</p>
<ul>
<li><strong>整数类型</strong> (<code>int</code>):用于存储整型数值,通常占用4字节。
<ul>
<li>例:<code>int a = 10;</code></li>
</ul>
</li>
<li><strong>浮点类型</strong> (<code>float</code>, <code>double</code>):用于存储小数,<code>float</code>通常占用4字节,<code>double</code>占用8字节。
<ul>
<li>例:<code>float pi = 3.14;</code></li>
</ul>
</li>
<li><strong>字符类型</strong> (<code>char</code>):用于存储单个字符,占用1字节。
<ul>
<li>例:<code>char letter = 'A';</code></li>
</ul>
</li>
</ul>
<p>C语言允许使用<strong>修饰符</strong>来改变基本类型的特性,如:</p>
<ul>
<li><code>short</code>:表示短整型,减少内存占用;</li>
<li><code>long</code>:表示长整型,增加数值范围;</li>
<li><code>unsigned</code>:表示无符号类型,仅存储非负数。</li>
</ul>
<p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">positive_num</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span> <span class="c1">// 无符号整数
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">long</span> <span class="kt">long</span> <span class="n">large_num</span> <span class="o">=</span> <span class="mi">1234567890</span><span class="p">;</span> <span class="c1">// 长整型
</span></span></span></code></pre></td></tr></table>
</div>
</div><h2 id="4-常量">4. <strong>常量</strong>
</h2><p>常量是指在程序运行期间其值不可改变的量。C语言通过 <code>const</code>关键字来声明常量。例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">const</span> <span class="kt">int</span> <span class="n">days_in_week</span> <span class="o">=</span> <span class="mi">7</span><span class="p">;</span> <span class="c1">// 一周的天数不会改变
</span></span></span></code></pre></td></tr></table>
</div>
</div><h2 id="5-基本输入输出">5. <strong>基本输入输出</strong>
</h2><ul>
<li><strong>输出函数 <code>printf()</code></strong>:用于向屏幕输出信息,常见的占位符有:
<ul>
<li><code>%d</code>:输出整数;</li>
<li><code>%f</code>:输出浮点数;</li>
<li><code>%c</code>:输出字符;</li>
<li><code>%s</code>:输出字符串。</li>
</ul>
</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Integer: %d, Float: %.2f</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mf">3.1415</span><span class="p">);</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>输入函数 <code>scanf()</code></strong>:用于从键盘读取输入,常见的格式符号与 <code>printf()</code>相似,使用 <code>&amp;</code>符号来获取变量的地址。</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">num</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">num</span><span class="p">);</span> <span class="c1">// 读取整数
</span></span></span></code></pre></td></tr></table>
</div>
</div><h2 id="6-运算符">6. <strong>运算符</strong>
</h2><p>C语言的运算符种类繁多,主要分为以下几类:</p>
<ul>
<li><strong>算术运算符</strong>:用于基本的数学运算,包括:
<ul>
<li><code>+</code>:加法;</li>
<li><code>-</code>:减法;</li>
<li><code>*</code>:乘法;</li>
<li><code>/</code>:除法(整数除法时,结果为整数);</li>
<li><code>%</code>:取模运算(只适用于整数)。</li>
</ul>
</li>
</ul>
<p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">10</span> <span class="o">%</span> <span class="mi">3</span><span class="p">;</span> <span class="c1">// result = 1
</span></span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>关系运算符</strong>:用于比较两个值,返回布尔结果(<code>1</code>表示真,<code>0</code>表示假)。
<ul>
<li><code>==</code>:等于;</li>
<li><code>!=</code>:不等于;</li>
<li><code>&gt;</code>:大于;</li>
<li><code>&lt;</code>:小于;</li>
<li><code>&gt;=</code>:大于等于;</li>
<li><code>&lt;=</code>:小于等于。</li>
</ul>
</li>
</ul>
<p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;a equals b&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>逻辑运算符</strong>:用于处理逻辑关系。
<ul>
<li><code>&amp;&amp;</code>:逻辑与,只有两个表达式都为真时,结果为真;</li>
<li><code>||</code>:逻辑或,任一表达式为真,结果为真;</li>
<li><code>!</code>:逻辑非,将表达式的结果取反。</li>
</ul>
</li>
</ul>
<p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">a</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">b</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Both a and b are positive numbers.&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="7-条件控制结构">7. <strong>条件控制结构</strong>
</h2><p>C语言中的条件控制结构用于控制程序执行的流程,主要包括:</p>
<ul>
<li><strong>if语句</strong>:用于条件判断,当条件成立时执行特定代码块。</li>
<li><strong>else语句</strong>:在 <code>if</code>条件不成立时执行。</li>
<li><strong>else if语句</strong>:用于多条件判断。</li>
</ul>
<p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">num</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Positive number&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">num</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Zero&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Negative number&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="8-循环控制结构">8. <strong>循环控制结构</strong>
</h2><p>C语言提供了三种常用的循环结构:</p>
<ul>
<li><strong>for循环</strong>:常用于已知循环次数的情况。</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>while循环</strong>:在条件成立时重复执行代码块,适用于未知循环次数的情况。</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>do&hellip;while循环</strong>:先执行一次代码块,然后在条件成立时继续循环。</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">do</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">i</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">);</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="9-函数与作用域">9. <strong>函数与作用域</strong>
</h2><ul>
<li><strong>函数</strong>是C语言中的重要组成部分,用于将代码逻辑封装成可重用的代码块。函数的声明和定义包括返回类型、函数名、参数列表和函数体。例如:</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">add</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>在调用函数时,参数会传递到函数内,函数执行完毕后将返回一个值。例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="nf">add</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span> <span class="c1">// result为8
</span></span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>局部变量与全局变量</strong>:C语言中的变量分为局部变量和全局变量。局部变量是在函数或代码块内部声明的变量,只能在其定义的范围内使用;全局变量是在函数外部声明的,整个程序都可以访问。</li>
</ul>
<h1 id="第二部分数组与字符串的详细介绍"><strong>第二部分:数组与字符串的详细介绍</strong>
</h1><p>在上一部分中,我们讲到了C语言的基本概念、控制结构和函数等内容。现在,我们将深入探讨C语言中的<strong>数组</strong>与<strong>字符串</strong>,它们是编程中用于处理多个数据的一些关键工具。</p>
<h2 id="1-数组概念">1. <strong>数组概念</strong>
</h2><p>数组是存储<strong>相同数据类型</strong>元素的<strong>连续内存块</strong>。它使得我们可以用同一个变量名来处理一组值,而不是为每个值都声明一个独立的变量。数组的元素通过下标(索引)进行访问,索引从 <code>0</code>开始。</p>
<h3 id="一维数组"><strong>一维数组</strong>
</h3><ul>
<li>一维数组可以看作是一个线性的数据集合。其语法为:</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">data_type</span> <span class="n">array_name</span><span class="p">[</span><span class="n">array_size</span><span class="p">];</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>例如,声明一个存储5个整数的数组:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">numbers</span><span class="p">[</span><span class="mi">5</span><span class="p">];</span> <span class="c1">// 创建一个包含5个整数的数组
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>我们可以通过下标来给数组元素赋值和访问元素:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">numbers</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> <span class="c1">// 给第一个元素赋值10
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">first_value</span> <span class="o">=</span> <span class="n">numbers</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="c1">// 获取第一个元素的值
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>也可以使用循环来遍历数组:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">numbers</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> <span class="c1">// 初始化数组
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span> <span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> <span class="c1">// 依次输出每个元素
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="数组初始化"><strong>数组初始化</strong>
</h3><p>数组可以在声明时直接初始化,也可以在运行时赋值:</p>
<ul>
<li>静态初始化(在声明时指定初始值):</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">numbers</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span> <span class="c1">// 初始化5个值
</span></span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>部分初始化时,未指定的元素会自动被初始化为 <code>0</code>:</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">numbers</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">};</span> <span class="c1">// 数组的剩余元素被初始化为0
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="多维数组"><strong>多维数组</strong>
</h3><p>C语言支持多维数组,常用的有二维数组。二维数组可以看作是一个<strong>矩阵</strong>,即行列形式的数据结构。声明语法如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">data_type</span> <span class="n">array_name</span><span class="p">[</span><span class="n">rows</span><span class="p">][</span><span class="n">cols</span><span class="p">];</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">matrix</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span> <span class="c1">// 3行3列的二维数组
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>二维数组的元素可以通过两个下标进行访问:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">matrix</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> <span class="c1">// 将第一行第二列的元素赋值为5
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>二维数组的遍历通常使用嵌套循环:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">matrix</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">},</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">}};</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span> <span class="n">matrix</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>在上述例子中,<code>matrix[2][3]</code>是一个2行3列的数组,遍历时通过嵌套的 <code>for</code>循环访问每个元素。</p>
<h2 id="2-字符串">2. <strong>字符串</strong>
</h2><p>字符串在C语言中被视为<strong>字符数组</strong>。C语言中没有专门的字符串数据类型,因此字符串通常是一个以空字符 <code>\0</code> 结尾的字符数组。该空字符标志着字符串的结束,且不会被显示输出。</p>
<h3 id="字符串的声明与初始化"><strong>字符串的声明与初始化</strong>
</h3><p>字符串可以通过字符数组来声明,并且可以直接初始化为字符串常量:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">str</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#34;Hello&#34;</span><span class="p">;</span> <span class="c1">// 自动在末尾添加&#39;\0&#39;
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>注意,这里的 <code>str</code>数组长度为6,因为 <code>&quot;Hello&quot;</code>有5个字符,加上末尾的空字符 <code>\0</code>总共6个字节。我们也可以手动初始化字符串:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">str</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="sc">&#39;H&#39;</span><span class="p">,</span> <span class="sc">&#39;e&#39;</span><span class="p">,</span> <span class="sc">&#39;l&#39;</span><span class="p">,</span> <span class="sc">&#39;l&#39;</span><span class="p">,</span> <span class="sc">&#39;o&#39;</span><span class="p">,</span> <span class="sc">&#39;\0&#39;</span><span class="p">};</span> <span class="c1">// 手动添加结束符
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="字符串输入输出"><strong>字符串输入输出</strong>
</h3><p>可以使用 <code>printf()</code>输出字符串,也可以使用 <code>scanf()</code>读取字符串。特别地,<code>scanf()</code>读取字符串时,不需要写 <code>&amp;</code>符号,因为字符串本质上是指针(稍后我们会详细讨论指针)。</p>
<ul>
<li>输出字符串:</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%s&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> <span class="c1">// 输出字符串
</span></span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>输入字符串:</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%s&#34;</span><span class="p">,</span> <span class="n">str</span><span class="p">);</span> <span class="c1">// 从用户输入获取字符串
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>不过,使用 <code>scanf()</code>时有一个重要问题:它只能读取<strong>空格之前的内容</strong>,遇到空格会停止输入。如果需要读取包含空格的字符串,可以使用 <code>gets()</code>函数(已废弃,不推荐)或 <code>fgets()</code>函数:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">fgets</span><span class="p">(</span><span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">),</span> <span class="n">stdin</span><span class="p">);</span> <span class="c1">// 读取带有空格的输入
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="常用字符串处理函数"><strong>常用字符串处理函数</strong>
</h3><p>C语言的 <code>string.h</code>库提供了一系列处理字符串的函数,如:</p>
<ul>
<li><code>strlen()</code>:计算字符串长度。</li>
<li><code>strcpy()</code>:复制字符串。</li>
<li><code>strcat()</code>:拼接字符串。</li>
<li><code>strcmp()</code>:比较两个字符串。</li>
</ul>
<p>示例:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str1</span><span class="p">[</span><span class="mi">20</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#34;Hello&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">str2</span><span class="p">[</span><span class="mi">20</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#34;World&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="nf">strcat</span><span class="p">(</span><span class="n">str1</span><span class="p">,</span> <span class="n">str2</span><span class="p">);</span> <span class="c1">// 将str2拼接到str1后
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">str1</span><span class="p">);</span> <span class="c1">// 输出&#34;HelloWorld&#34;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="3-数组与字符串的常见操作">3. <strong>数组与字符串的常见操作</strong>
</h2><h3 id="数组与指针"><strong>数组与指针</strong>
</h3><p>在C语言中,数组名实际上是一个指向数组第一个元素的指针。我们可以通过指针运算来访问数组元素:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">arr</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">arr</span><span class="p">;</span> <span class="c1">// p指向数组的第一个元素
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">));</span> <span class="c1">// 输出第二个元素的值,结果为2
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="字符串的常见问题"><strong>字符串的常见问题</strong>
</h3><ul>
<li><strong>数组越界</strong>:如果字符串数组的大小不足以容纳字符串和结束符 <code>\0</code>,可能会导致内存越界的问题。因此在声明字符串数组时要确保有足够的空间。</li>
<li><strong>空字符问题</strong>:字符串末尾必须有一个 <code>\0</code>,否则可能导致程序在输出或操作字符串时出现错误或崩溃。</li>
</ul>
<h2 id="4-字符串与数组的区别">4. <strong>字符串与数组的区别</strong>
</h2><p>尽管字符串是以字符数组的形式存在,但处理方式上仍有细微的区别:</p>
<ul>
<li>字符数组可以包含任意字符,不必以 <code>\0</code>结尾;</li>
<li>字符串必须以 <code>\0</code>结尾,<code>printf</code>等函数遇到 <code>\0</code>时才会停止输出。</li>
</ul>
<h1 id="第三部分指针详解"><strong>第三部分:指针详解</strong>
</h1><p>在前面的部分,我们讨论了数组和字符串,并简要提到了指针的概念。现在我们将深入讨论<strong>指针</strong>,这是C语言中最强大、但也最难掌握的概念之一。指针在C语言中的作用非常重要,尤其是在处理内存、数组、函数参数和动态分配内存时。</p>
<h2 id="1-指针的基本概念">1. <strong>指针的基本概念</strong>
</h2><p>指针是<strong>存储另一个变量的地址</strong>的变量。也就是说,指针指向存储在内存中的一个特定位置,而这个位置存储了某个值。通过指针,可以间接地访问和修改存储在该位置的值。</p>
<h3 id="指针声明"><strong>指针声明</strong>
</h3><p>在C语言中,指针通过类型名和一个星号(<code>*</code>)声明。它的基本语法为:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">data_type</span> <span class="o">*</span><span class="n">pointer_name</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><code>data_type</code>:指针所指向的变量的类型,例如 <code>int</code>, <code>float</code>等。</li>
<li><code>pointer_name</code>:指针变量的名称。</li>
</ul>
<p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="c1">// 声明一个指向整数的指针p
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="指针的地址和解引用"><strong>指针的地址和解引用</strong>
</h3><ul>
<li><strong>&amp;运算符</strong>:取地址运算符,返回变量的内存地址。</li>
<li>*<strong>运算符</strong>:解引用运算符,返回指针指向的变量的值。</li>
</ul>
<p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span> <span class="c1">// p存储变量a的地址
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Address of a: %p</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">p</span><span class="p">);</span> <span class="c1">// 输出变量a的地址
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Value of a: %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span> <span class="c1">// 通过指针访问变量a的值,结果为10
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>在这个例子中,<code>p</code>存储了 <code>a</code>的地址,而 <code>*p</code>则访问 <code>a</code>的值。</p>
<h2 id="2-指针与数组的关系">2. <strong>指针与数组的关系</strong>
</h2><p>在C语言中,数组名实际上就是一个<strong>指向数组第一个元素的指针</strong>。因此,指针和数组之间有非常密切的关系。</p>
<p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">arr</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">arr</span><span class="p">;</span> <span class="c1">// p指向数组的第一个元素
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span><span class="p">);</span> <span class="c1">// 输出10,相当于arr[0]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">));</span> <span class="c1">// 输出20,相当于arr[1]
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>这里,<code>p</code>指向 <code>arr[0]</code>,<code>p + 1</code>指向 <code>arr[1]</code>,通过解引用 <code>*(p+1)</code>可以访问数组的第二个元素。</p>
<p><strong>总结指针与数组的关系</strong>:</p>
<ul>
<li><code>arr</code>实际上是一个指向 <code>arr[0]</code>的指针;</li>
<li><code>arr[i]</code>等价于 <code>*(arr + i)</code>;</li>
<li>指针可以通过指针运算遍历数组。</li>
</ul>
<h2 id="3-指针与函数">3. <strong>指针与函数</strong>
</h2><p>在C语言中,指针与函数有着紧密的关系。通过指针,我们可以实现以下两种主要功能:</p>
<ul>
<li><strong>函数参数传递</strong>:通过传递指针,可以使得函数内部对传递参数的修改在函数外部生效。</li>
<li><strong>指向函数的指针</strong>:通过指针来引用和调用函数。</li>
</ul>
<h3 id="通过指针传递参数"><strong>通过指针传递参数</strong>
</h3><p>C语言中函数的参数传递是<strong>值传递</strong>,也就是说,函数接收到的是参数的副本。如果希望函数修改原始参数,可以通过指针来传递参数的地址。</p>
<p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">swap</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">temp</span> <span class="o">=</span> <span class="o">*</span><span class="n">a</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">a</span> <span class="o">=</span> <span class="o">*</span><span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="o">*</span><span class="n">b</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="nf">swap</span><span class="p">(</span><span class="o">&amp;</span><span class="n">x</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">y</span><span class="p">);</span> <span class="c1">// 传递x和y的地址
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;x = %d, y = %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">);</span> <span class="c1">// 输出:x = 10, y = 5
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>在这个例子中,<code>swap</code>函数通过指针修改了 <code>x</code>和 <code>y</code>的值,使得函数外的 <code>x</code>和 <code>y</code>被交换。</p>
<h3 id="函数指针"><strong>函数指针</strong>
</h3><p>指针不仅可以指向变量,还可以指向<strong>函数</strong>。一个函数指针可以存储某个函数的地址,并通过这个指针调用该函数。</p>
<p>函数指针的声明语法如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">return_type</span> <span class="p">(</span><span class="o">*</span><span class="n">pointer_name</span><span class="p">)(</span><span class="n">parameter_types</span><span class="p">);</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>例如,声明一个指向返回 <code>int</code>类型、接受两个 <code>int</code>参数的函数指针:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">func_ptr</span><span class="p">)(</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>我们可以将一个函数的地址赋给函数指针,并通过指针调用该函数:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">add</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">func_ptr</span><span class="p">)(</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">)</span> <span class="o">=</span> <span class="n">add</span><span class="p">;</span> <span class="c1">// 将函数add的地址赋给指针
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="nf">func_ptr</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span> <span class="c1">// 通过指针调用函数
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Result: %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">result</span><span class="p">);</span> <span class="c1">// 输出:Result: 7
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="4-指针的分类">4. <strong>指针的分类</strong>
</h2><p>指针在C语言中有多个分类,每种指针类型在不同的场景下使用。以下是几种常见的指针类型:</p>
<h3 id="空指针null指针"><strong>空指针(NULL指针)</strong>
</h3><p>空指针是指向**&ldquo;无效&quot;地址**的指针。通常将一个指针赋值为 <code>NULL</code>来表明它不指向任何有效的内存地址。在实际编程中,空指针常用于指针初始化或检查指针是否有效。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// p不指向任何有效地址
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>使用空指针可以避免一些未初始化指针带来的错误。</p>
<h3 id="悬空指针"><strong>悬空指针</strong>
</h3><p>悬空指针是指一个指针指向了被释放或不存在的内存地址。它是造成<strong>内存访问错误</strong>的常见原因。为了避免悬空指针,在释放动态分配的内存后,应该将指针设为 <code>NULL</code>。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="nf">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span> <span class="c1">// 动态分配内存
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">free</span><span class="p">(</span><span class="n">p</span><span class="p">);</span> <span class="c1">// 释放内存
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">p</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> <span class="c1">// 避免悬空指针
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="野指针"><strong>野指针</strong>
</h3><p>野指针指的是指向未知地址或非法内存地址的指针。野指针的行为是不可预料的,可能导致程序崩溃或产生未定义的行为。在使用指针时,要确保指针指向合法的内存区域。</p>
<h2 id="5-指针与动态内存管理">5. <strong>指针与动态内存管理</strong>
</h2><p>C语言提供了一套标准库函数来进行<strong>动态内存分配</strong>,它们包括:</p>
<ul>
<li><code>malloc()</code>:分配指定大小的内存块,返回指向该内存块的指针。如果分配失败,返回 <code>NULL</code>。</li>
<li><code>calloc()</code>:与 <code>malloc()</code>类似,但会初始化分配的内存为0。</li>
<li><code>free()</code>:释放之前用 <code>malloc()</code>或 <code>calloc()</code>分配的内存块。</li>
</ul>
<p>例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="nf">malloc</span><span class="p">(</span><span class="mi">5</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span> <span class="c1">// 分配5个int大小的内存
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="n">p</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Memory allocation failed</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1">// 初始化数组
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span> <span class="o">*</span> <span class="mi">10</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1">// 输出数组内容
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%d &#34;</span><span class="p">,</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nf">free</span><span class="p">(</span><span class="n">p</span><span class="p">);</span> <span class="c1">// 释放内存
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>在这个例子中,<code>malloc</code>函数分配了足够存储5个整数的内存空间,并通过指针 <code>p</code>访问和操作这些内存。</p>
<h2 id="6-指针的常见错误">6. <strong>指针的常见错误</strong>
</h2><ul>
<li><strong>未初始化的指针</strong>:指针在使用前必须初始化。如果未初始化就使用指针,可能会导致程序崩溃或产生不确定的行为。</li>
<li><strong>内存泄漏</strong>:使用 <code>malloc</code>或 <code>calloc</code>动态分配内存后,必须使用 <code>free</code>释放内存,否则会导致内存泄漏。</li>
<li><strong>解引用空指针</strong>:解引用空指针会导致程序崩溃。在解引用指针之前,必须确保指针指向有效的内存区域。</li>
</ul>
<h1 id="第四部分结构体联合体与指针的结合使用"><strong>第四部分:结构体、联合体与指针的结合使用</strong>
</h1><p>在上一部分中,我们深入讨论了C语言中的指针。现在我们继续探讨<strong>结构体</strong>和<strong>联合体</strong>,并进一步学习它们如何与指针结合使用。在C语言中,结构体和联合体是非常重要的数据类型,常用于定义复杂的数据结构,例如链表、树等。</p>
<h2 id="1-结构体struct">1. <strong>结构体(Struct)</strong>
</h2><p>结构体是一种用户自定义的数据类型,它允许将不同类型的变量组合成一个单一的实体。结构体特别适合用于描述复杂的对象或记录,例如描述一名学生的学号、姓名和成绩等信息。</p>
<h3 id="结构体的声明"><strong>结构体的声明</strong>
</h3><p>结构体的声明格式如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">structure_name</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">data_type1</span> <span class="n">member1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">data_type2</span> <span class="n">member2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>例如,定义一个表示学生信息的结构体:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">Student</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">id</span><span class="p">;</span> <span class="c1">// 学号
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">char</span> <span class="n">name</span><span class="p">[</span><span class="mi">50</span><span class="p">];</span> <span class="c1">// 姓名
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kt">float</span> <span class="n">grade</span><span class="p">;</span> <span class="c1">// 成绩
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="结构体变量的定义与访问"><strong>结构体变量的定义与访问</strong>
</h3><p>定义结构体变量时,可以使用结构体名称。例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">Student</span> <span class="n">s1</span><span class="p">;</span> <span class="c1">// 定义结构体变量s1
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>访问结构体的成员时使用点运算符(<code>.</code>):</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">s1</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="mi">1001</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nf">strcpy</span><span class="p">(</span><span class="n">s1</span><span class="p">.</span><span class="n">name</span><span class="p">,</span> <span class="s">&#34;Alice&#34;</span><span class="p">);</span> <span class="c1">// 将字符串&#34; Alice&#34;复制到name成员
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">s1</span><span class="p">.</span><span class="n">grade</span> <span class="o">=</span> <span class="mf">95.5</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>通过这种方式,我们可以操作和访问结构体中的各个成员。</p>
<h3 id="结构体初始化"><strong>结构体初始化</strong>
</h3><p>结构体变量可以在声明时初始化:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">Student</span> <span class="n">s1</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1001</span><span class="p">,</span> <span class="s">&#34;Alice&#34;</span><span class="p">,</span> <span class="mf">95.5</span><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="结构体数组"><strong>结构体数组</strong>
</h3><p>与基本类型数组类似,我们可以定义结构体数组来存储多个结构体变量。例如,定义一个存储多名学生信息的结构体数组:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">Student</span> <span class="n">students</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">1001</span><span class="p">,</span> <span class="s">&#34;Alice&#34;</span><span class="p">,</span> <span class="mf">95.5</span><span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">1002</span><span class="p">,</span> <span class="s">&#34;Bob&#34;</span><span class="p">,</span> <span class="mf">89.0</span><span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span><span class="mi">1003</span><span class="p">,</span> <span class="s">&#34;Charlie&#34;</span><span class="p">,</span> <span class="mf">92.3</span><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="2-结构体与指针">2. <strong>结构体与指针</strong>
</h2><p>指针可以与结构体结合使用,以更高效地操作结构体,尤其是在函数参数传递和动态内存分配时。</p>
<h3 id="结构体指针的声明"><strong>结构体指针的声明</strong>
</h3><p>结构体指针的声明与普通指针相同,只是类型为结构体类型。例如,声明一个指向 <code>Student</code>结构体的指针:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">Student</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>我们可以让指针 <code>p</code>指向某个结构体变量的地址:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">s1</span><span class="p">;</span> <span class="c1">// p指向结构体变量s1的地址
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="通过指针访问结构体成员"><strong>通过指针访问结构体成员</strong>
</h3><p>通过指针访问结构体成员时,不能直接使用点运算符,而是使用箭头运算符(<code>-&gt;</code>)。例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;ID: %d</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">id</span><span class="p">);</span> <span class="c1">// 访问结构体成员id
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Name: %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">);</span> <span class="c1">// 访问结构体成员name
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Grade: %.2f</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">p</span><span class="o">-&gt;</span><span class="n">grade</span><span class="p">);</span> <span class="c1">// 访问结构体成员grade
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>这种方式避免了结构体的大量复制,特别是在传递结构体作为函数参数时,指针更加高效。</p>
<h3 id="结构体指针与动态内存分配"><strong>结构体指针与动态内存分配</strong>
</h3><p>结构体指针可以与 <code>malloc()</code>函数结合,动态分配结构体内存。例如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">struct</span> <span class="n">Student</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">Student</span> <span class="o">*</span><span class="p">)</span><span class="nf">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span> <span class="n">Student</span><span class="p">));</span> <span class="c1">// 动态分配结构体内存
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">if</span> <span class="p">(</span><span class="n">p</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">-&gt;</span><span class="n">id</span> <span class="o">=</span> <span class="mi">1004</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="nf">strcpy</span><span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> <span class="s">&#34;David&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> <span class="n">p</span><span class="o">-&gt;</span><span class="n">grade</span> <span class="o">=</span> <span class="mf">88.5</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>分配完成后,可以像普通结构体指针一样操作和访问结构体成员,使用完成后需要记得释放内存:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">free</span><span class="p">(</span><span class="n">p</span><span class="p">);</span> <span class="c1">// 释放内存
</span></span></span></code></pre></td></tr></table>
</div>
</div><h2 id="3-联合体union">3. <strong>联合体(Union)</strong>
</h2><p><strong>联合体</strong>与结构体类似,也是一种自定义的数据类型,但它允许多个成员共用同一块内存空间。联合体中的所有成员<strong>共享同一个内存地址</strong>,因此在某一时刻,联合体只能存储一个成员的值。</p>
<h3 id="联合体的声明"><strong>联合体的声明</strong>
</h3><p>联合体的声明格式与结构体类似:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4