天天看點

C語言數組常見使用錯誤

作者:霸都嵌入式

C語言中,數組是一種資料結構,它可以存儲一個固定大小的相同類型元素的順序集合。數組是用來存儲一系列資料,但它往往被認為是一系列相同類型的變量。在使用數組時,我們需要注意一些常見的錯誤和陷阱,以避免程式出現邏輯錯誤或者運作錯誤。

C語言數組易錯用法有以下幾種:

數組的定義和初始化

- 在定義數組時,必須指定數組的類型和大小,大小必須是一個大于零的整數常量或者符号常量。不能使用變量或者表達式作為數組的大小。例如:

int a[10]; //正确,定義一個包含10個整數的數組
#define N 5
int b[N]; //正确,定義一個包含N個整數的數組,N是符号常量
int n = 3;
int c[n]; //錯誤,不能使用變量作為數組的大小
int d[2 + 3]; //錯誤,不能使用表達式作為數組的大小           

- 在初始化數組時,可以使用花括号{}将用來初始化的各個數值括起來,并且各個數值之間要用逗号分隔開來。如果隻給部分元素賦初值,後面的元素預設為0。如果給全部元素賦初值,第一維的長度可以省略。例如:

int a[5] = {1, 2, 3, 4, 5}; //正确,給全部元素賦初值
int b[5] = {1, 2}; //正确,隻給前兩個元素賦初值,後面三個元素預設為0
int c[] = {1, 2, 3, 4, 5}; //正确,給全部元素賦初值,省略第一維的長度
int d[5] = {1, 2, {3, 4, 5}}; //錯誤,不能嵌套花括号           

數組的通路和指派

- 在通路和指派數組元素時,必須使用合法的下标或者索引。下标或者索引是放在方括号[]内,跟在數組名稱的後面。下标或者索引從0開始,到數組長度減1結束。不能越界通路或者指派數組元素。例如:

int a[5] = {1, 2, 3, 4, 5};
printf("%d\n", a[0]); //正确,輸出第一個元素的值
printf("%d\n", a[4]); //正确,輸出最後一個元素的值
printf("%d\n", a[5]); //錯誤,越界通路
a[2] = 6; //正确,修改第三個元素的值
a[-1] = 7; //錯誤,越界指派           

- 在通路和指派多元數組元素時,必須使用多個下标或者索引。每個次元對應一個下标或者索引。例如:

int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
printf("%d\n", a[0][0]); //正确,輸出第一行第一列的元素的值
printf("%d\n", a[2][3]); //正确,輸出最後一行最後一列的元素的值
printf("%d\n", a[3][4]); //錯誤,越界通路
a[1][2] = 13; //正确,修改第二行第三列的元素的值
a[0][1] = 14; //錯誤,隻給出了一個下标           

數組的傳遞和傳回

- 在将數組作為函數參數傳遞時,必須注意以下幾點:

- 數組名在函數調用時會被轉換為指向數組第一個元素的指針,是以不能直接使用sizeof運算符來擷取數組的大小。例如:

void printArray(int a[], int n) {
  printf("%d\n", sizeof(a)); //錯誤,輸出的是指針的大小,而不是數組的大小
  for(int i = 0; i < n; i++) {
	  printf("%d ", a[i]); //正确,使用下标通路數組元素
  }
  printf("\n");
}
int main() {
  int a[5] = {1, 2, 3, 4, 5};
  printArray(a, 5); //正确,傳遞數組名和數組長度
  return 0;
}           

- 在函數定義時,可以使用數組名和方括号來聲明數組參數,也可以使用指針來聲明。但是必須指定第一維的長度,或者使用星号“*”表示指針。例如:

//使用數組名和方括号聲明數組參數
void printArray(int a[], int n); //正确,省略第一維的長度
void printArray(int a[5], int n); //正确,指定第一維的長度
void printArray(int a[][4], int n); //正确,指定第二維的長度
void printArray(int a[][], int n); //錯誤,不能省略第二維的長度
//使用指針聲明數組參數
void printArray(int *a, int n); //正确,使用星号表示指針
void printArray(int (*a)[4], int n); //正确,使用括号和星号表示二維數組的指針           

- 在函數調用時,可以使用數組名或者指向數組元素的指針作為實參。但是必須保證明參和形參的類型和長度相比對。例如:

void printArray(int a[], int n);
int main() {
  int a[5] = {1, 2, 3, 4, 5};
  int b[6] = {6, 7, 8, 9, 10, 11};
  int *p = &a[0];
  printArray(a, 5); //正确,傳遞數組名和長度
  printArray(p, 5); //正确,傳遞指針和長度
  printArray(b, 6); //錯誤,傳遞的數組長度不比對
  return 0;
}           

- 在函數内部,可以修改數組參數的内容,這些修改會影響到實參。是以,在不需要修改實參的情況下,可以使用const修飾符來保護數組參數。例如:

void swap(int a[], int i, int j) {
  int temp = a[i];
  a[i] = a[j];
  a[j] = temp;
}
void print(const int a[], int n) {
  for(int i = 0; i < n; i++) {
 	 printf("%d ", a[i]);
  }
  printf("\n");
  //a[0] = 0; //錯誤,不能修改const修飾的數組參數
}
int main() {
  int a[5] = {1, 2, 3, 4, 5};
  swap(a, 0, 4); //正确,交換第一個和最後一個元素
  print(a, 5); //正确,列印數組元素
  return 0;
}           

- 在将數組作為函數傳回值傳回時,必須注意以下幾點:

- C語言不允許直接傳回一個局部數組變量的值,因為局部變量在函數結束後會被銷毀,傳回的位址将無效。例如:

int *getArray() {
  int a[5] = {1, 2, 3, 4, 5}; //定義一個局部數組變量
  return a; //錯誤,傳回一個無效的位址
}
int main() {
  int *p = getArray(); //錯誤,接收一個無效的位址
  printf("%d\n", p[0]); //錯誤,通路一個無效的位址
  return 0;
}           

- 如果要傳回一個數組的值,有以下幾種方法:

- 使用靜态數組變量。靜态變量在程式運作期間一直存在,不會被銷毀,是以可以傳回其位址。但是靜态變量隻能初始化一次,而且不能保證線程安全。例如:

int *getArray() {
  static int a[5] = {1, 2, 3, 4, 5}; //定義一個靜态數組變量
  return a; //正确,傳回一個有效的位址
}
int main() {
  int *p = getArray(); //正确,接收一個有效的位址
  printf("%d\n", p[0]); //正确,通路一個有效的位址
  return 0;
}           

- 使用動态記憶體配置設定。動态記憶體配置設定可以在運作時根據需要配置設定和釋放記憶體空間,是以可以傳回其位址。但是動态記憶體配置設定需要手動管理記憶體,避免記憶體洩漏或者野指針。例如:

int *getArray() {
  int *a = (int *)malloc(5 * sizeof(int)); //使用malloc函數配置設定動态記憶體
  if(a == NULL) { //檢查是否配置設定成功
    printf("Memory allocation failed\n");
    exit(1);
  }
  for(int i = 0; i < 5; i++) { //給動态數組指派
 	 a[i] = i + 1;
  }
  return a; //正确,傳回一個有效的位址
}
int main() {
  int *p = getArray(); //正确,接收一個有效的位址
  printf("%d\n", p[0]); //正确,通路一個有效的位址
  free(p); //使用free函數釋放動态記憶體
  return 0;
}           

- 使用指向數組的指針作為函數參數。指向數組的指針可以用來傳遞和修改數組的内容,是以可以在函數内部給其指派,并在函數外部使用其值。但是指向數組的指針需要指定數組的長度,并且要保證與實參相比對。例如:

void getArray(int (*a)[5]) { //使用指向數組的指針作為函數參數
  for(int i = 0; i < 5; i++) { //給指針所指向的數組指派
	  (*a)[i] = i + 1;
  }
}
int main() {
  int a[5]; //定義一個數組變量
  getArray(&a); //傳遞數組變量的位址給函數
  printf("%d\n", a[0]); //正确,通路數組變量的值
  return 0;
}           

系列文章持續更新,如果覺得有幫助請點贊+關注!

繼續閱讀