C语言万字基础笔记总结(三)上

简介: 简介:C语言学习笔记,记录所学,便于复习。 由于篇幅过大,考虑到观感,准备分多篇记录。学习视频:《带你学C带你飞》IDE:Dev-C++ 5.11

一、函数


1、函数初识

  • 例:打印一段话
# include <stdio.h>
void hello();  //函数声明 
void hello()  //函数定义 
{
  printf("你好哇,nice to meet you"); 
 } 
int main(){
  hello();  //函数调用 
  return 0;
}

输出结果为:

你好哇,nice to meet you

①、函数声明

有时候,函数声明也可以省略(子函数放在主函数前面的时候)

但在初学阶段,为了养成良好的习惯,建议写上函数声明。

②、函数定义

  • 基本框架如下:
类型名  函数名(参数列表)  //参数列表可以空,但是()不能省
{
    函数体
}

2、函数的参数和输出值

- 例:编写一个函数sum,由用户输入参数n,计算1+2+…+(n-1)+n的结果并返回

# include <stdio.h>
int sum(int n);  //函数声明
int sum(int n)    //函数定义
{
  int result = 0;
  for(;n>0;n--)   //经典的用一个循环进行求和
  {
    result += n;
  }
  return result;
 } 
int main(){
  int n,result;
  printf("请输入您想输入的数字:");
  scanf("%d", &n);
  result = sum(n);   //函数调用
  printf("求和结果为:%d", result); 
  return 0;
}

输出为:

请输入您想输入的数字:10
求和结果为:55

值得一提的是函数遇到return 就会立即返回值。

比如说,利用if条件语句的时候,有两个return,是有两个返回值吗?不是的,只有一个!

  • 例:编写一个函数max,接受两个整型参数,并返回它们中较大的值。


# include <stdio.h>
int max(int x, int y);  //函数声明
int max(int x, int y)  //函数定义
{
  if (x > y)   //条件语句比较大小
  {
    return x;
  }
  else
  {
    return y;
  }
}
int main(){
  int a, b, c;
  printf("请输入你想比较的两个数:");
  scanf("%d %d", &a, &b);
  c = max(a, b);
  printf("这两个数中较大的那个是:%d", c);
  return 0;
}

子函数(max函数)和主函数(main函数)中的参数名是不冲突的,可以一样,也可以不一样。

3、指针函数

函数也可以返回指针类型的数据

  • 例:根据输入的字母返回不同的值


# include <stdio.h>
char *getword(char);
char *getword(char c)
{
  if (c == 'A'){  //这里的if语句也可以写成switch语句
    return "Apple";
  }
  else if (c == 'D'){
    return "Dog";
  }
  else{
    return "None";
  }
}
int main(){
  char input;
  printf("请输入一个字母:");
  scanf("%c", &input);
  printf("输出结果为:%s\n", getword(input));
  return 0;
}

值得注意的是不要返回局部变量的指针

  • 例:将上述例子加以修改
# include <stdio.h>
char *getword(char);
char *getword(char c)
{
  char str1[] = "Apple";
  char str2[] = "Dog";
  if (c == 'A'){
    return str1;  //返回局部变量
  }
  else if (c == 'D'){
    return str2;
  }
  else{
    return "None";
  }
}
int main(){
  char input;
  printf("请输入一个字母:");
  scanf("%c", &input);
  printf("输出结果为:%s\n", getword(input));
  return 0;
}

编译会报warring:

[Warning] function returns address of local variable [-Wreturn-local-addr]

运行结果如下:

请输入一个字母:A
输出结果为:P

因此,返回局部变量的指针是不可取的

4、函数指针

像数组指针一样,它是一个指针。

# include <stdio.h>
int sum(int);
int sum(int num){
  return num + num;
} 
int main(){
  int num;
  int (*fs)(int);  //函数指针
  printf("请输入一个数字:");
  scanf("%d", &num);
  fs = sum;  //函数名就是函数的地址
  printf("%d + %d = %d\n", num, num, (*fs)(num)); 
  return 0;
}


二、全局变量和局部变量


1、局部变量

在函数里边定义的变量

2、全局变量

在函数外边定义的变量

Q:哪些情况下,会使用全局变量呢?

A:当一个程序中,多个函数都需要使用一个变量,那么就会用到全局变量

全局变量的一些特点:

  • ①、如果不对全局变量进行初始化,那么它会初始化为0。
  • ②、如果在函数的内部存在一个与全局变量同名的局部变量,那么在这个函数中,全局变量不起作用。
  • 例:


# include <stdio.h>
void func();
int a, b = 110;   // 定义全局变量a,b  其中a=0,b=110
void func()
{
  int b;   //定义局部变量b 
  a = 119;
  b = 120;   //对a,b进行赋值
  printf("在func中的值,a = %d, b = %d\n", a, b) ;
 } 
int main(){
  printf("在main中的值,a = %d, b = %d\n", a, b);
  func();
  printf("func函数处理后,在main中的值,a = %d, b = %d\n", a, b);
  return 0;
}

运行结果:

在main中的值,a = 0, b = 110
在func中的值,a = 119, b = 120
func函数处理后,在main中的值,a = 119, b = 110

简单分析一下:

首先,定义了全局变量a=0,b=110,所以在第一次打印的时候,结果是不变的;第二次打印,是作用在func函数中,此时定义了一个局部变量b,并对a=119,b=120进行分开赋值,打印结果应该是赋值后的值;第三次打印,是在main函数中,由于a是全局变量,func对其影响是有的,所以a=119继续保持,而b在func中变成了局部变量,赋值仅仅作用在func函数中,到了main函数,又变回110。

全局变量不建议大量使用,原因:

  • ①、使用全局比那辆会使程序占用更多的内存
  • ②、污染命名空间,降低程序可读性
  • ③、提高了程序的耦合性,当代码体比较长了之后,时间再久一点,自己会忘记全局变量受到哪些函数的影响了。


三、作用域


  • 当变量被定义在程序的不同位置时,它的作用范围时不一样的,这个作用范围就是作用域。
  • C语言编译器可以确认的4种不同的作用域
    ①、代码块作用域
    ②、文件作用域
    ③、原型作用域
    ④、函数作用域


四、链接属性


  • external(外部的)

多个文件中声明的同名标识符表示同一个实体

  • internal(内部的)

单个文件中声明的同名标志符表示同一个实体

  • none(无)

声明的同名标识符被当作独立不同的实体

  • 注意:

只有具备文件作用域的标识符才能拥有external或internal的链接属性,其他作用域的标识符都是none属性。

默认情况下,具备文件作用域的标识符拥有external属性。也就是说该标识符允许跨文件访问。对于external属性的标识符,无论在不同文件中声明多少次,表示的都是同一个实体。

默认情况下,具备文件作用域的标识符拥有external属性。也就是说该标识符允许跨文件访问。对于external属性的标识符,无论在不同文件中声明多少次,表示的都是同一个实体。

使用static关键字可以使得原先拥有external属性的标识符变为internal属性有两点需要注意

①、使用static关键字修改链接属性,支队具有文件作用域的标识符生效(对于拥有其他作用域的标识符时另一种功能)

②、链接属性只能修改一次,也就是说一旦将标识符的链接属性变为internal,就无法变为external。


五、生存期


C语言的变量拥有两种生存期:

  • 静态存储期

具有文件作用域的变量属于静态存储期,函数也属于静态存储期。属于静态存储期的变量在程序执行期间将一致占据存储空间,知道程序关闭才释放。

  • 自动存储期

具有代码块作用域的变量一般情况下属于自动存储期。属于自动存储期的变量在代码块结束时将自动释放存储空间。


六、存储类型


C语言提供了五种不同的存储类型。


  • 自动变量(auto)

在代码块中声明的变量默认的存储类型就是自动变量,使用关键字auto来描述。

  • 寄存器变量(register)

将一个变量声明为寄存器变量,那么该变量就有可能被存放于寄存器中。

寄存器变量和自动变量在很多方面是一样的,它们都拥有代码块作用域,自动存储期和空连接属性。

将变量声明为寄存器变量,那么就没办法通过取址运算符获得该变量的地址。

  • 静态局部变量(static)

使用static来声明局部变量,那么就可以将局部变量指定为静态局部变量。

static的局部变量具有静态存储期,所以它的生存期与全局变量一样,直到程序结束才释放。

  • 外部变量(extern)

extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。

也就是说,extern关键字是用于告诉编译器这个变量或函数在别的地方已经定义过了,不要急着报错

  • typedef
相关文章
|
6月前
|
存储 人工智能 算法
【C语言】自学终极笔记
【C语言】自学终极笔记
106 0
|
3月前
|
测试技术 C语言 C++
【C语言刷题训练——6】鹏哥C语言刷题训练营笔记,含代码讲解改进
【C语言刷题训练——6】鹏哥C语言刷题训练营笔记,含代码讲解改进
|
3月前
|
存储 C语言
【C语言】鹏哥C语言刷题训练营——第5节内容笔记(含代码全面分析和改进,讲解)
【C语言】鹏哥C语言刷题训练营——第5节内容笔记(含代码全面分析和改进,讲解)
|
5月前
|
C语言
|
5月前
|
C语言
|
6月前
|
C语言
C语言(指针详解)重点笔记:指针易错点,都是精华
C语言(指针详解)重点笔记:指针易错点,都是精华
75 0
|
存储 编译器 C语言
C语言笔记第03章:数组(四)
C语言笔记第03章:数组
95 0
|
编译器 C语言 索引
C语言笔记第03章:数组(一)
C语言笔记第03章:数组
104 0
|
6月前
|
NoSQL Redis C语言
|
C语言
C语言初阶 牛客网刷题笔记(将持续更新..)
C语言初阶 牛客网刷题笔记(将持续更新..)
C语言初阶 牛客网刷题笔记(将持续更新..)