当前位置:   article > 正文

嵌入式学习笔记十一——C语言数组作为函数参数和标识符的作用域和可见性问题

嵌入式学习笔记十一——C语言数组作为函数参数和标识符的作用域和可见性问题

数组作为函数参数

1.数组本身作为函数参数 

在函数中无法计算数组的长度,需要将长度作为参数 传入函数
      形参  --写成数组形式  还需要数组长度 
      实参  --数组名,数组长度

  1. printArrray(int a[],int len) //形参
  2. //printArrray (int *a,int len) ---编译器最终理解的形式
  3. //调用
  4. printArray(a,len);

2.一维字符型数组做函数参数
一维字符型数组

用来存放字符串 

因为处理的是字符串数据,字符串操作的 依据,主要看结束标志 '\0'而不是 数组长度

所以: 一维字符型数组做函数参数,

1.   形参  数组形式
2.   实参  数组名 

练习:写Gets(char s[]),Strlen(char s[]),Strcat(char dest[],char src[]),Strcpy(char dest[],char src[]),Strcmp(char s1[],char s2[])函数,实现相对应的功能

  1. #include <stdio.h>
  2. void Puts(char s[])
  3. {
  4. int i = 0;
  5. while (s[i] != '\0')
  6. {
  7. printf ("%c",s[i]);
  8. ++i;
  9. }
  10. putchar('\n');
  11. }
  12. void Gets(char s[])
  13. {
  14. int i = 0;
  15. while ((s[i] = getchar()) != '\n') //s[i] = getchar()须括起来
  16. //关系运算 != 比 = 优先级高。
  17. {
  18. ++i;
  19. }
  20. s[i] = '\0';
  21. }
  22. int Strlen(char s[])
  23. {
  24. int i;
  25. while (s[i] != '\0')
  26. ++i;
  27. return i;
  28. }
  29. void Strcpy(char dest[],char src[])
  30. {
  31. int i = 0;//记得一定要初始化
  32. while (src[i] != '\0')
  33. {
  34. dest[i] = src[i];
  35. ++i;
  36. }
  37. dest[i] = '\0';
  38. }
  39. void Strcat(char dest[],char src[])
  40. {
  41. int i = 0;
  42. int j = 0;
  43. while (dest[i] != '\0')
  44. ++i;
  45. while (src[j] != '\0')
  46. {
  47. dest[i] = src[j];
  48. ++i;
  49. ++j;
  50. }
  51. dest[i] = '\0';
  52. }
  53. int Strcmp(char s1[],char s2[])
  54. {
  55. int i = 0;
  56. int ret;
  57. while (s1[i] == s2[i] && s1[i] != '\0' && s2[i] != '\0')
  58. {
  59. ++i;
  60. }
  61. ret = s1[i]-s2[i];
  62. return ret;
  63. }
  64. int main(void)
  65. {
  66. char s[100];
  67. char ss[100] = "hello";
  68. Gets(s);
  69. Puts(s);
  70. printf("%d\n",Strlen(s));
  71. // Strcpy(ss,s);
  72. // Strcat(ss,s);
  73. // Puts(ss);
  74. printf("%d\n",Strcmp(s,ss));
  75. return 0;
  76. }

3.二维数组做函数参

总结:
    形参   --- 二维数组形式 + 行数    //本质 一维数组 + 长度
    实参   --- 数组名       + 行数    //

练习:实现一个函数,1.求二维数组元素的和 2.找出二维数组中主对角上最大值 

  1. #include <stdio.h>
  2. void printArray(int (*a)[4],int row)
  3. {
  4. int i = 0;
  5. int j = 0;
  6. for (i = 0;i < row;++i)
  7. {
  8. for (j = 0;j < 4;++j)
  9. {
  10. printf("%d ",a[i][j]);
  11. }
  12. putchar('\n');
  13. }
  14. }
  15. int addArray(int (*a)[4],int row)
  16. {
  17. int i = 0;
  18. int j = 0;
  19. int sum = 0;
  20. for (i = 0;i < row;++i)
  21. {
  22. for (j = 0;j < 4;++j)
  23. {
  24. sum += a[i][j];
  25. }
  26. }
  27. return sum;
  28. }
  29. int findMax(int a[][4],int row)
  30. {
  31. int i = 0;
  32. int max = a[0][0];
  33. while (i < row)
  34. {
  35. if (max < a[i][i])
  36. max = a[i][i];
  37. ++i;
  38. }
  39. return max;
  40. }
  41. int main(void)
  42. {
  43. int a[][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
  44. int row = sizeof(a)/sizeof(a[0]);
  45. printf("%d\n",addArray(a,row));
  46. printArray(a,row);
  47. printf("max = %d\n",findMax(a,row));
  48. return 0;

4.二维字符数组做函数参数

 与二维整型数组 使用方式相同 
    形参   --- 二维数组形式 + 行数    //本质 一维数组 + 长度
    实参   --- 数组名       + 行数    //

  注意:
      1.不要和一维字符型数组传参搞混 
        一维字符型数组,主要用来存放 字符串数据 
        而字符串数据有结束标志('\0'),故,传参时,不需要传长度 

       2.二维字符型数组,用来存储多个字符串
       要操作时,往往都是操作多个字符串,而多个字符串没有所谓结束的标志。
       看的是数组长度(行数)

练习:1. 实现一个输入多个字符串函数2.排序    //插入排序3.二分查找 

  1. #include <stdio.h>
  2. #include <string.h>
  3. void printStr(char s[][10],int row)
  4. {
  5. int i = 0;
  6. for (i = 0;i < row;++i)
  7. {
  8. puts(s[i]);
  9. }
  10. }
  11. void inputStr(char s[][10],int row)
  12. {
  13. int i = 0;
  14. for (i = 0;i < row;++i)
  15. {
  16. gets(s[i]);
  17. }
  18. }
  19. void insertSort(char s[][10],int row)
  20. {
  21. int i = 0;
  22. char ss[10];
  23. for (i = 0;i < row;++i)
  24. {
  25. strcpy(ss,s[i]);
  26. int j = i;
  27. while(j > 0 && strcmp(ss,s[j-1]) < 0)
  28. {
  29. strcpy(s[j],s[j-1]);
  30. j--;
  31. }
  32. strcpy(s[j],ss);
  33. }
  34. }
  35. int seekStr(char s[][10],int row,char s1[])
  36. {
  37. int begin = 0;
  38. int end = row - 1;
  39. int mid;
  40. int ret = 0;
  41. while (begin <= end)
  42. {
  43. mid = (begin+end)/2;
  44. if (strcmp(s[mid],s1) < 0)
  45. begin = mid + 1;
  46. else if (strcmp(s[mid],s1) > 0)
  47. end = mid - 1;
  48. else
  49. {
  50. ret = mid;
  51. break;
  52. }
  53. }
  54. return ret;
  55. }
  56. int main(void)
  57. {
  58. char s[5][10];
  59. int row = sizeof(s)/sizeof(s[0]);
  60. char s1[10] = "hello";
  61. inputStr(s,row);
  62. insertSort(s,row);
  63. printStr(s,row);
  64. printf("s[%d] = %s\n",seekStr(s,row,s1),s[seekStr(s,row,s1)]);
  65. return 0;
  66. }


  总结:

   1.一维整型数组 做函数参数
   形参 --- 数组形式 + 数组长度 
   实参 --- 数组名   + 数组长度    
   2.一维字符型数组 做函数参数
   形参 --- 数组形式  
   实参 --- 数组名   
   原型: 一维字符型数组 主要用来存储字符串数据 
   3.二维整型数组 做函数参数
   形参 --- 数组形式 + 行数 //本质 就是一维数组的长度 
   实参 --- 数组名   + 行数 
   4.二维字符型数组 做函数参数
   形参 --- 数组形式 + 行数 //本质 就是一维数组的长度 
   实参 --- 数组名   + 行数

2.标识符的作用域与可见性问题:

作用域:名字 作用的访问 
可见性 :程序运行到某一个位置 哪些名字可以被使用(被看见)

1.作用域:

局部作用域 
        { 
        }  //花括号范围内 就叫局部作用域 
 全局作用域 
       不在 任何一个 {} 范围之内 

 (1)在局部作用域定义的变量 --- 局部变量  
   特点:局部变量 空间 一般都开栈上, 如果不初始化,局部变量中的值是随机值(垃圾值)

  (2)在全局作用域 定义的变量 --- 全局变量 
   特点:全局变量 空间  全局区, 如果不初始化,默认初始化为0

2.标识符的可见性的规则:

1.先定义,后使用 
2.同一作用域中,不能有同名标识符
3.在不同的作用域,同名标识符,相互之间没有影响 
4.如果是不同的作用域,但是作用域之间存在嵌套关系, 则内层的作用域的同名标识符,会屏蔽外层的作用域的同名标识符。 (就近原则)

3.生命周期

(1)局部变量的生命周期 

      从程序运行到定义处开始存在,到程序运行到 它作用范围结束时销毁

(2)全局变量(静态变量)的生命周期

     从程序开始运行时就存在了,直到整个程序运行结束时,销毁 
      注意:全局变量和静态变量,不能用"变量"进行初始化

4.存储类别的关键字

auto :表示它是一个自动变量 (局部变量)  ---  自动申请 自动释放 

static:static 修饰局部变量  此时 会被放在 全局区(静态区)此时局部变量的生命周期被延长
注意:
   1.static 修饰局部变量 --只会被初始化一次 

   2.static 修饰的变量 -- 具有继承性

   3.static 修饰的变量 -- 只能用常量初始化 (不能用变量初始化)

   4.static 修饰全局变量 表示限定全局变量的作用域位本文件,别的文件不能通过extern来声明使用。用途: 保护私有数据 , 防止被引用 。
   5.修饰函数 //声明函数 在别处的定义的 函数,static 修饰函数作用和修饰全局变量作用相同, 限定作用域为本文件,别的文件不能通过extern来声明使用 

register:寄存器  表示,把变量 存储 寄存器中 //建议性//register 修饰的变量 ,不能 做 & //(取地址) 

extern:外部的  ---表示你的变量 是存在外部的   //多文件编程 //不在当前文件中  //只能 声明 全局变量 

 static总结:

1.修饰变量 

(1)修饰局部变量 
表示将局部变量存放到静态区。 延长声明周期。
存在静态区的变量:
a.不能用变量初始化 
b.只会被初始化一次 
c.反复使用该变量时,值具有继承性。

(2)全局变量   
限定作用域为本文件,别的文件不能通过extern来声明使用 

2.修饰函数         
限定作用域为本文件,别的文件不能通过extern来声明使用  

         
                
                
                
                
          

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/951415
推荐阅读
相关标签
  

闽ICP备14008679号