首页 > 其他分享 >【C语言基础】函数与变量

【C语言基础】函数与变量

时间:2024-09-08 21:54:52浏览次数:8  
标签:存储 函数 int C语言 静态 变量 定义

函数的分类:

  • 从定义角度分:
    • 库函数:随C语言编译器提供的。无须用户定义,只需在程序前包含含有该函数原型的头文件。
    • 自定义函数:用户自己定义的函数。
  • 从函数返回结果角度分:
    • 有返回值函数:函数在执行完需要返回一个值,这个值就是函数的值。
    • 无返回值函数:函数只执行任务,不返回任何值。用户在定义时可指定此类函数的返回值 为“空类型”,即void。
  • 从函数调用时的数据传递角度分:
    • 有参函数:主调函数和被调函数之间有数据的传递。
    • 无参函数:主调函数和被调函数之间不进行数据传递。无参函数通常用来执行指定操作。

每个程序有且只有一个main函数。main函数可以调用其它函数,但main函数是不能被调用的。

1 函数的定义与声明

一般形式:

返回值类型 函数名(参数列表)
{
    函数体
}

例子:

#include <stdio.h>
void iCompare(int Num1, int Num2);

int Add(int Num1, int Num2)
{
	int sum;
	sum = Num1 + Num2;
	return sum;
}

main()
{
	int a, b, sum;
	a = 10;
	b = 20;
	sum = Add(a, b);
	printf("%d + %d = %d\n", a, b, sum);

	iCompare(a, b);
}

void iCompare(int Num1, int Num2)
{

	if (Num1 > Num2)
		printf("%d > %d\n", Num1, Num2);
	else if (Num1 == Num2)
		printf("%d = %d\n", Num1, Num2);
	else
		printf("%d < %d\n", Num1, Num2);
}

运行结果:

  • 无参函数没有参数列表;
  • 若自定义函数在调用函数之后定义,需要先进行声明才可使用。上例中,iCompare函数被定义在main函数之后,因此在程序开头的第2行进行了声明:void iCompare(int Num1, int Num2); 
  • 若自定义函数在调用函数之前定义,无须进行声明。
  • 函数的定义是互相平行且独立的,所以不可以在函数中嵌套定义另一个函数,即使是在main函数中也不可以。

声明一个函数:

  • 函数的声明格式必须与该函数定义的函数头保持一致。
  • 必须以分号";"作为语句的结尾。

定义与声明的区别:

  • 定义:是在编译器里创建一个对象,为这个对象分配一块内存,并给对象取一个名字,取的名字就是变量名或对象名。这里为对象分配内存。
  • 声明:告诉编译器这个名字已经分配到一块内存了,并且这个名字现在归此声明所用,别的地方不允许再使用这个名字。这里没有为对象分配内存。

2 函数的参数

  1. 定义或声明函数时,函数参数为形式参数,即形参;
  2. 调用函数时,函数参数为实际参数,即实参。实参可以是常量、变量、表达式和函数等。

数组也可作为函数参数:

  • 可使用数组元素作为函数参数;
  • 可使用数组名作为函数。

例子:

#include <stdio.h>
void ShowArrayMember(int iMember);
void ShowArray(int iArray[]);
void EvaluateArray(int iArray[10]);

main()
{
	int iArray[10] = { 1,2,3,4,5 };
	ShowArray(iArray);

	EvaluateArray(iArray);
	ShowArray(iArray);
	for (int i = 0; i < 10; i++)
		ShowArrayMember(iArray[i]);
}

void ShowArrayMember(int iMember)
{
	printf("Current array member is: %d\n", iMember);
}

void ShowArray(int iArray[])
{
	printf("Current array members are:\n");
	for (int i = 0; i < 10; i++)
		printf("%d ", iArray[i]);
	printf("\n");
}

void EvaluateArray(int iArray[10])
{
	printf("Evaluate array...\n");
	for (int i = 0; i < 10; i++)
		iArray[i] = iArray[i] + 10*i;
}

运行结果:

3 变量与变量的存储

3.1 局部变量与全局变量

局部变量与全局变量
变量类型说                              明
局部变量在函数内部定义的变量。无法被别的函数使用。
全局变量在所有函数外部定义的变量。属于整个源文件,可以在程序中的任何位置进行访问。如果外部文件要进行调用,需要使用extern进行引用。

3.2 变量的存储

变量的存储类别有两种形式:静态存储和动态存储。可以通过存储类修饰符来告诉编译器要处理什么样的类型变量,具体有:自动(auto),静态(static),寄存器(register),外部(extern)。

3.2.1 静态存储与动态存储

从变量的产生时间上可以分为静态存储和动态存储。静态存储是指程序运行时分配固定的存储方式;动态存储是在程序运行期间根据需要进行动态的分配存储空间。

内存中,系统提供给用户的存储空间分为三部分:程序区,静态存储区,动态存储区。程序区用来存放用户要执行的程序段,数据分别放在静态存储区和动态存储区中。

  • 静态存储区:储存全局变量。全局变量从程序执行时开始分配存储单元,占据固定的内存空间,直到程序终止时,才释放其所占的存储单元。
  • 动态存储区:在调用函数时,其局部变量也被保存到动态存储区中,分配内存空间,当函数结束执行,返回到主调函数时,,该变量所占用的空间将被释放,此时局部变量也将消失。对于形参函数,只有在调用该函数时才能为形参分配内存空间,调用完成后会将所有的空间释放。

3.2.2 auto变量

函数内凡未加存储类型说明的变量均视为自动变量,也就是说自动变量可以省略说明符auto。所以,以下两种变量定义是等价的:

{
    int a, b;
    ...
}
{
    auto int a, b;
    ...
}

自动变量属于动态存储方式。

3.2.3 static变量

3.2.3.1 静态局部变量
  • 在函数内定义,属于静态存储类别。它的生存期是整个源程序。
  • 静态局部变量的作用域与自动变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后,虽然该变量还存在,但不能使用它,如果再次调用定义它的函数,又可继续使用。
  • 对于基本类型的静态局部变量,如果在说明时没有赋以初值,则系统自动赋予0值。而对于自动变量,如果不赋初值,那么它的值是不确定的。

例子:

#include <stdio.h>
int AddStatic(int x)
{
	static int i = 0;
	i += x;
	return i;
}

int AddAuto(int x)
{
	int i = 0;
	i += x;
	return i;
}

main()
{
	int i, StaticSum, AutoSum;
	for (int i = 1; i < 10; i++)
	{
		StaticSum = AddStatic(i);
		AutoSum = AddAuto(i);
		printf("%d: StaticSum = %d, AutoSum = %d\n", i, StaticSum, AutoSum);
	}
}

运行结果:

3.2.3.2 静态全局变量

非静态全局变量与静态全局变量在存储方式上是相同的,但作用域是不同的。非静态全局变量的作用域是整个源程序,而静态全局变量的作用域是该变量的源文件,在同一源程序的其它源文件中不能使用它。

3.2.4 register变量

寄存器变量允许将局部变量的值存放在CPU中的寄存器中,使用时不需要访问内存,而直接从寄存器中读写。寄存器变量的说明符是register。

  • 用户无法获得寄存器变量的地址。
  • 如果想要有效地利用register关键字,必须像汇编语言程序员那样了解处理器的内部结构,知道可用于存放变量的寄存器的数量、种类和工作方式。对于这些细节,不同计算机可能是不同的。因此,对于一个要具备可移植性的程序来说,register的作用是不大的。

3.2.5 extern变量

当一个源文件中的函数想引用其它源文件中的变量,就可以用extern来声明外部变量。声明格式:

extern 数据类型 外部变量表;

  • 在函数内的extern变量声明,表示引用本源文件中的外部变量;
  • 在函数外的extern变量声明(通常在文件开头),表示引用其它文件中的外部变量。

如果外部变量不在文件的开头定义,其有效的作用范围只限于定义到文件结束处。

4 内部函数与外部函数

函数是C语言程序中的最小单位,通常把一个或多个函数保存为一个文件,这个文件称为源文件。定义一个函数,这个函数就要被另外的函数所调用。但当一个源程序由多个源文件组成时,可以指定函数不能被其它文件调用。

内部函数与外部函数
函数类型说                                 明
内部函数

又称为静态函数。只能被所在的源文件所使用,不能被其它文件调用。

定义时,只需在函数返回值类型前加上关键字static即可,格式如下:

static 返回值类型 函数名(参数列表)

好处:不同的开发者可以分别编写不同的函数,而不必担心所使用的函数是否会与其它源文件中的函数同名。

外部函数

外部函数是可以被其它源文件调用的函数。

定义时,使用关键字extern进行修饰,extern关键字可以省略;

使用时,需要先用关键字extern声明所用的函数是外部函数。

标签:存储,函数,int,C语言,静态,变量,定义
From: https://blog.csdn.net/weixin_46891908/article/details/142018833

相关文章

  • C语言深入理解指针4
    1.回调函数回调函数是通过函数指针调用的函数将函数指针作为参数传递给另一个函数,当这个函数指针被用来调用其所指向的函数时,被调用的函数就是回调函数,回调函数不是应该由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外一方调用的,用于对该事件或条件进行响应......
  • 鹏哥C语言自定义笔记重点(44-)
    44.不能给地址复制,strcpy拷贝过去连带着\045.46. 47. 48.strstr   //查找子串的一个函数49.strtok  //切割字符串 50.strerror   //返回错误码,所对应的错误信息 检查的是文件51.如果不正确则返回0  52.memcpy负责拷贝两块独立空间......
  • 20240909_011725 c语言 预处理
    在C语言中,第一行#include<stdio.h>是一个预处理指令,用于包含(或说,导入)标准输入输出库(StandardInputOutputLibrary)的头文件。这个库提供了进行输入输出操作的函数,比如printf()用于在屏幕上显示输出,scanf()用于从键盘读取输入等。具体来说:#include是一个预处理指令,告诉编译器......
  • 20240909_021725 c语言 骨架结构
    关注骨架结构明确intmainreturn0的意义与功能......
  • Python函数之lambda函数
    温馨提示:如果读者没有学过def定义函数,请先看这里定义形式<函数名>=lambda<参数列表>:<返回值>等同于:def<函数名>(<参数列表>): return<返回值>也可以定义为匿名函数(没有名字的函数):lambda<参数列表>:<返回值>可以确认lambda函数对象的类型与def定义的一样,都是fu......
  • Python和MATLAB(Java)及Arduino和Raspberry Pi(树莓派)点扩展函数导图
    ......
  • c语言第五章循环1.0
    #define_CRT_SECURE_NO_WARNINGS循环结构例1.11到100求和#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>intmain(){   intsum=0;   for(inti=1;i<=100;i++){      sum=sum+i;   }   printf("%d",sum);   return......
  • 【Python】对象(包括类、函数)取名方法
    先上干货,通用的:字母:A-Za-z下划线:_数字:0-9(注意:数字不能在开头)理论上可以使用中文变量名,但强烈不建议使用。合法名字举例abcdef GoodCoder AD_fhrygfuigfrA_a_007 __NAME123 _P_T__123456 Cc_Dd _不合法名字举例666Code C++ 1+1=2 (5)4654ty54F 0.123 [email protected]......
  • Python函数之def定义函数
    链接想研究Python函数?看这里函数怎样取名?看这里有参数的函数还可以怎么传参?看这里一、无参数函数结构def<函数名>():#强制要求 <函数体>#可省略 return<返回值>#可省略程序举例用函数的Helloworld程序:#prints'HelloWorld\nDone'#Author:GoodCoder666d......
  • Python函数之*[参数名]和**[参数名]的用处
    一、*[参数名]调用合法调用普通调用*参数名一般写成*args,如:deffunc(*args): print(args)可以试着调用func:>>>func(1)(1,)>>>func()()>>>func(1,2,3)(1,2,3)>>>func(dict(),set(),str(),int())({},set(),'',0)所以,我们发现,这......