10W+字C语言硬核总结(九),值得阅读收藏!

2.2.3 指针数组(元素为指针)


2.2.3.1 栈区指针数组



//数组做函数函数,退化为指针
void array_sort(char** arr,int len){
 for (int i = 0; i < len; i++){
  for (int j = len - 1; j > i; j --){
   //比较两个字符串
   if (strcmp(arr[j-1],arr[j]) > 0){
    char* temp = arr[j - 1];
    arr[j - 1] = arr[j];
    arr[j] = temp;
   }
  }
 }
}
//打印数组
void array_print(char** arr,int len){
 for (int i = 0; i < len;i++){
  printf("%s\n",arr[i]);
 }
 printf("----------------------\n");
}
void test(){
 //主调函数分配内存
 //指针数组
 char* p[] = { "bbb", "aaa", "ccc", "eee", "ddd"};
 //char** p = { "aaa", "bbb", "ccc", "ddd", "eee" }; //错误
 int len = sizeof(p) / sizeof(char*);
 //打印数组
 array_print(p, len);
 //对字符串进行排序
 array_sort(p, len);
 //打印数组
 array_print(p, len);
}


2.2.3.2 堆区指针数组


//分配内存
char** allocate_memory(int n){
 if (n < 0 ){
  return NULL;
 }
 char** temp = (char**)malloc(sizeof(char*) * n);
 if (temp == NULL){
  return NULL;
 }
 //分别给每一个指针malloc分配内存
 for (int i = 0; i < n; i ++){
  temp[i] = malloc(sizeof(char)* 30);
  sprintf(temp[i], "%2d_hello world!", i + 1);
 }
 return temp;
}
//打印数组
void array_print(char** arr,int len){
 for (int i = 0; i < len;i++){
  printf("%s\n",arr[i]);
 }
 printf("----------------------\n");
}
//释放内存
void free_memory(char** buf,int len){
 if (buf == NULL){
  return;
 }
 for (int i = 0; i < len; i ++){
  free(buf[i]);
  buf[i] = NULL;
 }
 free(buf);
}
void test(){
 int n = 10;
 char** p = allocate_memory(n);
 //打印数组
 array_print(p, n);
 //释放内存
 free_memory(p, n);
}



2.2.4二维数组三种参数形式


2.2.4.1 二维数组的线性存储特性


void PrintArray(int* arr, int len){
 for (int i = 0; i < len; i++){
  printf("%d ", arr[i]);
 }
 printf("\n");
}
//二维数组的线性存储
void test(){
 int arr[][3] = {
  { 1, 2, 3 },
  { 4, 5, 6 },
  { 7, 8, 9 }
 };
 int arr2[][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 int len = sizeof(arr2) / sizeof(int);
 //如何证明二维数组是线性的?
 //通过将数组首地址指针转成Int*类型,那么步长就变成了4,就可以遍历整个数组
 int* p = (int*)arr;
 for (int i = 0; i < len; i++){
  printf("%d ", p[i]);
 }
 printf("\n");
 PrintArray((int*)arr, len);
 PrintArray((int*)arr2, len);
}



2.2.4.2 二维数组的3种形式参数


//二维数组的第一种形式
void PrintArray01(int arr[3][3]){
 for (int i = 0; i < 3; i++){
  for (int j = 0; j < 3; j++){
   printf("arr[%d][%d]:%d\n", i, j, arr[i][j]);
  }
 }
}
//二维数组的第二种形式
void PrintArray02(int arr[][3]){
 for (int i = 0; i < 3; i++){
  for (int j = 0; j < 3; j++){
   printf("arr[%d][%d]:%d\n", i, j, arr[i][j]);
  }
 }
}
//二维数组的第二种形式
void PrintArray03(int(*arr)[3]){
 for (int i = 0; i < 3; i++){
  for (int j = 0; j < 3; j++){
   printf("arr[%d][%d]:%d\n", i, j, arr[i][j]);
  }
 }
}
void test(){
 int arr[][3] = { 
  { 1, 2, 3 },
  { 4, 5, 6 },
  { 7, 8, 9 }
 };
 PrintArray01(arr);
 PrintArray02(arr);
 PrintArray03(arr);
}



2.3总结


2.3.1 编程提示


源代码的可读性几乎总是比程序的运行时效率更为重要


只要有可能,函数的指针形参都应该声明为 const。


在多维数组的初始值列表中使用完整的多层花括号提高可读性


2.3.2 内容总结


在绝大多数表达式中,数组名的值是指向数组第 1 个元素的指针。这个规则只有两个例外,sizeof 和对数组名&。


指针和数组并不相等。当我们声明一个数组的时候,同时也分配了内存。但是声明指针的时候,只分配容纳指针本身的空间。


当数组名作为函数参数时,实际传递给函数的是一个指向数组第 1 个元素的指针。


我们不单可以创建指向普通变量的指针,也可创建指向数组的指针。


上一篇:呐,c语言学习你想要的都在这里


下一篇:熬夜整理的C语言/C++万字总结(四)