## 數組 本篇主要介紹:`一維二維數組`、`字元數組`、`數組名和初始化註意點`以及`位元組序`。 ### 一維數組 #### 初始化 有以下幾種方式對數組初始化: ```c // 定義一個有5個元素的數組,未初始化 int a[5]; // 定義一個有5個元素的數組,將第一個初始化0,後面幾個元素 ...
數組
本篇主要介紹:一維二維數組
、字元數組
、數組名和初始化註意點
以及位元組序
。
一維數組
初始化
有以下幾種方式對數組初始化:
// 定義一個有5個元素的數組,未初始化
int a[5];
// 定義一個有5個元素的數組,將第一個初始化0,後面幾個元素預設初始化為0
int a[5] = {0};
// 定義一個有5個元素的數組,5個元素都初始化為:2,3,4,5,6
int a[5] = {2, 3, 4, 5, 6};
// 【推薦】
// 和上一種在功能上是相同的。編譯器會根據初始化列表中的元素個數(5個)自動確定數組a的大小為5
int a[] = {2,3,4,5,6};
Tip:以上寫法創建的數組都是不可變大小的
。
練習1
題目
:int a[5] = {1}
,請問 a 的每個值是多少?
#include <stdio.h>
int main() {
// 將第一個初始化1,後面幾個元素預設初始化為0
int a[5] = {1};
int i;
for (i = 0; i < 5; i++) {
printf("%d ", a[i]);
}
return 0;
}
輸出:1 0 0 0 0
。
在C和C++中,當我們創建數組時,如果沒有為數組的所有元素提供初始值,那麼剩下未被初始化指定初始值的元素會被預設初始化。對於基本數據類型(如int、float、double等),預設情況下,未初始化的元素將被設置為0
練習2
題目
:如果不對 a[5]
進行初始化,將輸出什麼?
#include <stdio.h>
int main() {
- int a[5] = {1};
+ int a[5];
int i;
for (i = 0; i < 5; i++) {
printf("%d\n", a[i]);
}
return 0;
}
輸出隨機數:
開始運行...
4198784
0
4198464
0
-2014700240
運行結束。
練習3
題目
:如果將int a[5];
提到全局作用於中,輸出什麼?
#include <stdio.h>
int a[5];
int main() {
int i;
for(i = 0; i < 5; i++){
printf("%d ", a[i]);
}
return 0;
}
輸出: 0 0 0 0 0
練習4
題目
:這段代碼有什麼錯誤?
#include <stdio.h>
int main() {
int i = 10;
int a[i] = {0};
return 0;
}
運行:
開始運行...
# 不允許初始化可變大小的對象。即 i 是可變的。
/workspace/CProject-test/main.c:5:11: error: variable-sized object may not be initialized
int a[i] = {0};
^
1 error generated.
運行結束。
結論
:數組長度不能是變數。
如果換成 #define 常量
還有問題嗎?
#include <stdio.h>
#define i 10
int main() {
// int i = 10;
int a[i] = {0};
return 0;
}
如果換成 #define 常量
就正常,前面我們知道 #define 是文本替換
。
數組名
題目
:定義一個數組a,請問 a
、&a[0]
、&a
的含義是什麼?
#include <stdio.h>
int main() {
int a[5] ={1};
printf("%p\n", a);
printf("%p\n", &a[0]);
printf("%p\n", &a);
printf("-----\n");
printf("%p\n", a + 1);
printf("%p\n", &a[0] + 1);
printf("%p\n", &a + 1);
return 0;
}
運行:
開始運行...
0x7ffdfb131f00
0x7ffdfb131f00
0x7ffdfb131f00
-----
0x7ffdfb131f04
0x7ffdfb131f04
0x7ffdfb131f14
運行結束。
Tip: printf 中的 %p 列印的就是記憶體地址
。記憶體地址通常以十六進位
形式表示。
上半部分都是輸出的都是 0x7ffdfb131f00
。
但下半部分加1後,結果明顯不同。其中:
0x7ffdfb131f04 - 0x7ffdfb131f00 = 0x4
,轉為十進位是4,一個 int 就是4個位元組0x7ffdfb131f14 - 0x7ffdfb131f00 = 0x14
,轉為十進位數是20,剛好是數組 a 的位元組數(5*4)
結論:
a
- 數組名。表示首元素的地址,加 1 是加一個元素(比如這裡4個位元組)&a[0]
- 表示首元素地址,加 1 是加一個元素(比如這裡4個位元組)&a
- 表示整個數組。加1相當於跨越了整個數組
冒泡排序
之前我們寫過冒泡排序的例子,我們將該示例用 C 語言重寫如下(函數部分後文會講):
#include <stdio.h>
void bubbleSort(int arr[], int n) {
// 比較輪數,每輪都會將一個值冒泡到正確的位置
for (int i = 0; i < n; i++) { // 第i輪冒泡
for (int j = 0; j < n - i - 1; j++) { // 第i輪冒泡需要比較n-i-1次
// 出界則為 false,不會交換
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int arr[] = {4, 3, 2, 1};
// 計算數組長度。sizeof(arr) - 返回數據類型或變數所占記憶體大小(位元組);arr[0] - 一個元素的位元組數。
int length = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, length);
// 輸出
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
return 0;
}
// Output: 1 2 3 4
位元組序
位元組序(Byte Order)是指在存儲和表示多位元組數據時,位元組的順序
排列方式。
思考這樣一個問題
int a[5]
有5個元素,每個元素4個位元組,在記憶體中是一塊連續的空間。表示如下:
索引 | a[0] | a[1] | a[2] | a[3] | a[4] |
---|---|---|---|---|---|
地址 | 0x100 | 0x104 | 0x108 | 0x10C | 0x110 |
我們可以將a[0]
稱作低地址
,a[4]
稱作高地址
。a數組中每個元素的四個位元組,最左側位元組稱作低地址
,最右側位元組稱作高地址
。就像這樣:
低地址 | 高地址 | ||
---|---|---|---|
________ | ________ | ________ | ________ |
數組 a 中每個元素中是一個整數,比如 a[0] = 1
,在記憶體中是4個位元組,共32位,其二進位表示為:00000000 00000000 00000000 00000001
。最左側是高位元組
,最右側是低位元組
,就像這樣:
高位元組 | 低位元組 | ||
---|---|---|---|
00000000 | 00000000 | 00000000 | 00000001 |
請問 1 的高位元組(00000000)放在低地址還是高地址?
大端序和小端序
不同的電腦架構和處理器採用不同的位元組序(Byte Order)。常見的位元組序有兩種:
大端序
(Big Endian),低位元組對應高地址,高位元組對應低地址。1 對應00000000 00000000 00000000 00000001
小端序
(Little Endian),低位元組對應低地址,高位元組對應高地址。1 對應00000001 00000000 00000000 00000000
低地址 | 高地址 | |||
---|---|---|---|---|
大端序 | 00000000 | 00000000 | 00000000 | 00000001 |
小端序 | 00000001 | 00000000 | 00000000 | 00000000 |
Tip: 不同位元組序的選擇涉及到如何組織和解釋二進位數據。位元組序的重要性體現在跨平臺數據交互和網路通信上。如果兩個設備使用不同的位元組序,就需要進行適當的數據轉換才能正確解讀和處理數據
二維數組
可以理解成一維數組中每個元素又是一個一維數組。例如 a[3][4]
就像這樣:
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 行 | ||||
1 行 | ||||
2 行 |
a[0]
、a[1]
、a[2]
,每一行就是一個一維數組。
初始化
有多種方式進行二維數組的初始化,效果也不盡相同。請看示例:
int a[3][4];
未初始化,數組 a 中都是隨機值。請看示例:
#include <stdio.h>
int main() {
int a[3][4];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", a[i][j]);
}
printf("\n");
}
return 0;
}
輸出:
開始運行...
-1833069321 32764 4198917 0
0 0 0 0
4198848 0 4198464 0
運行結束。
- 部分初始化。示例如下:
// 輸出:1 2 3 4 5 6 7 8 9 10 11 12
int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
// 輸出:1 0 0 0 5 6 0 0 0 0 0 0
int a[3][4] = {{1}, {5, 6}};
- 全部初始化。示例如下:
// 輸出:1 2 3 4 5 6 7 8 9 10 11 12
int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
// 0 0 0 0 0 0 0 0 0 0 0 0
// 此種寫法不能保證所有編譯器
int a[3][4] = {}
- 行數可以省略。以下兩行代碼等效:
int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
// 省略行。類似一維數組中省略元素個數。
int a[][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
數組名
題目
:定義一個二維數組a,請問 &a[0][0]
、a
、&a[0]
、&a
的含義是什麼?
#include <stdio.h>
int main() {
int a[3][4];
printf("%p\n", &a[0][0]);
printf("%p\n", a);
printf("%p\n", a[0]);
printf("%p\n", &a);
printf("-----\n");
printf("%p\n", &a[0][0] + 1);
printf("%p\n", a + 1);
printf("%p\n", a[0] + 1);
printf("%p\n", &a + 1);
return 0;
}
輸出:
開始運行...
0x7fffadc7d310
0x7fffadc7d310
0x7fffadc7d310
0x7fffadc7d310
-----
0x7fffadc7d314
0x7fffadc7d320
0x7fffadc7d314
0x7fffadc7d340
運行結束。
上半部分都是輸出的都是 0x7fffadc7d310
。
下半部分每個加1,差異就顯現出來。
0x7fffadc7d314 - 0x7fffadc7d310 = 0x4,轉為十進位是4個位元組
&a[0][0] + 1
0x7fffadc7d320 - 0x7fffadc7d310 = 0x10,轉為十進位是16個位元組,每個元素是4個位元組,也就是4(16/4)個元素,表示一行
a + 1
0x7fffadc7d314 - 0x7fffadc7d310 = 0x4,轉為十進位是4個位元組
a[0] + 1
0x7fffadc7d340 - 0x7fffadc7d310 = 0x30,轉為十進位是48個位元組,每個元素是4個位元組,也就是 12(48/4)個元素,表示整個數組
&a + 1
結論:
&a[0][0]
- 首行首元素地址,加 1 是加一個元素(比如這裡4個位元組)a
- 地址名,表示首行地址,加 1 就是加一行a[0]
- 首行首元素地址,加 1 是加一個元素(比如這裡4個位元組)&a
- 表示整個數組。加1相當於跨越了一個數組
練習
題目
:數組 a[3][4]
,哪個不能表示a[1][1]
的地址?
A、a[1] + 1
B、&a[1][1]
C、(*(a + 1)) + 1
D、a + 5
答案:D。
分析:根據上文學習,我們知道 A和B能表示,其中D是加5行,肯定錯。C由於沒學指針,暫時不管。
字元數組
在 C 語言中,字元串可以用字元數組來表示,即用一個數組來保存一串字元,每個字元用一個位元組來存儲,末尾有一個特殊的空字元 '\0' 來表示字元串的結束。
#include <stdio.h>
int main() {
char str[] = {'h', 'e', 'l', 'l', 'o', '\0'};
printf("%s", str);
return 0;
}
在字元數組的初始化末尾一定要添加空字元 '\0'(筆者使用的線上編輯器沒報錯),否則在使用字元串函數處理字元串時,可能會出現意外的錯誤。也可以將上面的代碼簡化為以下形式:
char str[] = "hello";
這樣就可以不用手動添加空字元了,編譯器會自動為字元串添加結尾的空字元。
練習
題目
:在輸入的字元串中,在指定位置插入指定字元
實現:
#include <stdio.h>
// string.h 是 C 語言中的頭文件,用於提供一些字元串處理操作的函數和巨集定義
#include <string.h>
void insertChar(char str[], int pos, char ch) {
// 獲取字元串的長度
int len = strlen(str);
// 檢查插入位置是否有效
if (pos < 0 || pos > len)
return;
// 將指定位置後的字元往後移動一位
for (int i = len; i >= pos; i--) {
str[i + 1] = str[i];
}
// 在指定位置插入字元
str[pos] = ch;
}
int main() {
char str[100];
int pos;
char ch;
printf("請輸入字元串。例如 hello world:\n");
scanf("%[^\n]", str);
printf("請輸入要插入的位置:");
scanf("%d", &pos);
printf("請輸入要插入的字元:");
scanf(" %c", &ch);
insertChar(str, pos, ch);
printf("\n修改後的字元串:%s\n", str);
return 0;
}
運行:
開始運行...
請輸入字元串。例如 hello world:
a-b-c d e-f-g
請輸入要插入的位置:4
請輸入要插入的字元:x
修改後的字元串:a-b-xc d e-f-g
運行結束。
出處:https://www.cnblogs.com/pengjiali/p/17485725.html
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接。