目录
c语言中的函数
函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数,即主函数 main() ;
您可以把代码划分到不同的函数中。在需要使用具体功能时随时调用;
函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实际主体。
C 标准库提供了大量的程序可以调用的内置函数。如printf,scanf等函数;
c语言中的函数的组成格式
在 C 语言中,函数由一个函数头和一个函数主体组成。
返回值类型 函数名(参数列表)
{
//函数主体;
return 0;
}
函数的封装实例
封装求和的函数;
int add(int a,int b) //封装一个名称为add的函数,其中有a,b 两个int类型的参数;
{
return (a+b); //返回值返回a+b;
}
c语言中函数的调用
函数在调用前需要将函数的声明;
调用函数时,传递所需参数,如果函数返回一个值,则可以存储返回值。
求和的函数的调用
int sum; //定义一个int类型的sum;
sum = add(10,20); //将add函数的两个参数a,b传参为10和20;并用sum接收函数返回的值;
函数参数
如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。
形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。
当调用函数时,有两种向函数传递参数的方式:
调用类型 | 描述 |
---|---|
传值调用 | 把参数的实际值复制给函数的形式参数。修改函数内的形式参数不会影响实际参数。 |
引用调用 | 通过指针传递方式,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。 |
指针作为函数参数问题
C语言中,指针作为函数参数是一种非常强大的功能,它允许我们将函数内部的操作影响到函数外部的变量。这是通过值传递的方式实现的,但在某些情况下可能会造成误解。
当我们在函数定义时看到 void swap(int p1, int p2),这里的 p1 和 p2 是形式参数,也称为形参。在函数调用时,如 swap(a, b),a 和 b 是实际参数,也称为实参。在函数调用过程中,实参的值会被复制到形参中,而不是形参指向内存地址的引用。因此,形参 p1 和 p2 是独立的,它们在函数内部进行的操作不会影响外部的 a 和 b。
为了解决这个问题,我们可以通过指针传递实参的地址。例如:
void swap(int *p1, int *p2) {
int temp = *p1; // 取出 p1 指向的值
*p1 = *p2; // 将 p2 指向的值赋给 p1 指向的位置
*p2 = temp; // 将 temp 的值赋给 p2 指向的位置
}
在这个 swap 函数中,p1 和 p2 是指向整数的指针。当调用 swap(&a, &b) 时,a 和 b 的地址被传递到函数中。函数内部通过指针操作交换了这两个地址指向的值,因此外部变量的值也被交换了。
指针作为函数参数的其他应用场景包括动态内存分配、数组操作和实现复杂的数据结构等。使用指针可以提高程序的效率,减少内存的使用,并允许更灵活的数据操作。然而,使用指针也需要谨慎,因为错误的指针使用可能导致内存泄漏、野指针访问和其他运行时错误。
总之,C语言中指针作为函数参数是提高程序性能和灵活性的关键,但也需要合理和谨慎地使用,以确保程序的正确性和稳定性。
数组作为函数参数问题
在C语言中,数组作为函数参数时,实际上传递的是数组的首地址,而不是整个数组。这意味着,如果你在函数内部修改了数组的值,那么这些更改会影响到函数外部的原始数组。下面是一个简单的示例,演示了如何将一个数组作为参数传递给函数,并在函数内部修改数组的值:
#include <stdio.h>
void func(int arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] *= 2;
}
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
func(arr, 5);
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
在上面的示例中,我们定义了一个名为func的函数,该函数接受一个整数数组和数组的大小作为参数。在函数内部,我们通过遍历数组并将每个元素乘以2来修改数组的值。然后,在main函数中,我们声明了一个整数数组arr,并将其传递给func函数。最后,我们打印出修改后的数组。
需要注意的是,当数组作为函数参数传递时,如果数组的大小是固定的,那么它将被作为常量处理。这意味着你不能在函数内部更改数组的大小。如果你需要动态大小的数组,可以考虑使用指针来代替数组作为函数参数。
c语言中的作用域
局部变量
在某个函数或块的内部声明的变量称为局部变量。它们只能被该函数或该代码块内部使用。局部变量在函数外部是不可知的。
全局变量
全局变量是定义在函数外部。全局变量在整个程序生命周期内都是有效的,全局变量可以被任何函数访问。也就是说,全局变量在声明后整个程序中都是可用的。
注意:在程序中,局部变量和全局变量的名称可以相同,但是在函数内,如果两个名字相同,会使用局部变量,全局变量不会被使用。
形式参数
函数的参数,形式参数,被当作该函数内的局部变量,如果与全局变量同名它们会优先使用。
全局变量与局部变量在内存中的区别:
- 全局变量保存在内存的全局存储区中,占用静态的存储单元;
- 局部变量保存在栈中,只有在所在函数被调用时才动态地为变量分配存储单元。
c语言中的数组
一维整型数组的定义
int a[3];
一维整型数组成员访问
a[0] a[1] a[2]
C 语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。
一维整数数组的赋值
定义时候赋初值
int a[3] = {1,2,3};
如果数组中赋值了个别成员后面没有赋值的成员都是0。
如果定义的时候不赋初值,后面只能通过遍历的形式挨个赋值。
数组成员的个数
数组成员的个数取决于方括号内的常量
int a[6] = {123,456,789};
数组成员个数取决于赋值的成员个数
int a[] = {1,2,3,4};
数组是构造类型,因为数组所占用字节的大小取决于数组成员的个数
数组是同种类型元素的集合。数组在内存上是连续存储的。
数组名是数组的首地址,它是一个常量(不能够自增或自减)
数组定义的格式:
成员类型 数组名[成员个数];
数组的类型是char [10],int [10];
数组中的成员表示
a[0],a[1],...a[9]。
c语言的编译器不会对数组进行越界检查数组分为一维数组,二维数组和多维数组。
一维整型数组的实例
#include <stdio.h>
int main(int argc, const char *argv[])
{
int arr[5]; //定义一维整型数组arr,内部有5个成员
printf("请输入5个整数>");
for(int i=0;i<5;i++){
scanf("%d",&arr[i]);
}
for(int i=0;i<5;i++){
printf("arr[%d] = %d\n",i,arr[i]);
}
return 0;
}
sizeof关键字
在C语言中,sizeof 是一个关键字,而不是一个函数。它用于获取数据类型或者变量所占用的内存大小,并以字节为单位返回结果。
#include <stdio.h>
int main(int argc, const char *argv[])
{
int arr[5];
printf("请输入> ");
//sizeof是关键字,它的作用是获取类型所占的字节数
//在如下实例中sizeof(arr) = 20字节
//sizeof(arr[0])=4字节,两者相除就是数组成员的个数
for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++){
scanf("%d",&arr[i]);
}
for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++){
printf("arr[%d] = %d\n",i,arr[i]);
}
return 0;
}
C语言中sizeof和strlen的区别
sizeof是关键字,sizeof可以用来求类型所占的字节数,
也可以用来获取变量所占的字节数。
strlen是一个函数,strlen只能用来获取字符串中字符的个数;
strlen在获取大小的时候遇到'\0'才会停止,而sizeof和'\0'无关;
strlen如果没有'\0',就无法获取大小;
一维字符数组
一维字符数组的定义
char arr[3];
一维字符数据的成员访问
arr[0] arr[1] arr[2]
一维字符数组赋初值(单个字符)
定义的时候赋初值
char arr[5] = {'h','e','l','l','o'};
char arr[3] = {0}; #将数组中所有的成员都赋值为0
先定义后赋值
char arr[5];
arr[0] = 'h';
arr[1] = 'e';
arr[2] = 'l';
arr[3] = 'l';
arr[4] = 'o';
一维字符数组赋值(字符串)
char arr[] = "hello";
注意:
如果上述的arr被赋值为"hello"字符串,字符数组的成员的个数是6。数组内部的成员分别是'h','e','l','l','o','\0'。('\0'为字符串结束符);
一维数组地址及地址加1问题
int a[3] = {111,222,333};
假如:a的地址0x1111;
&a[0] = 0x1111
&a[1] = 0x1115
&a[2] = 0x1119
a
:数组名,它是数组的首地址,是一个常量(0x1111)
a[0]
:数组中的第0个成员,a[0]对应的值是1111
&a[0]
:数组中第0个成员的地址,是0x1111
&a
:取整个数组的首地址,获取的地址是0x1111
a+1
:地址移动一个元素类型的大小移动了int(4)字节,地址是0x1115
a[0]+1
:a[0]中的值加了1,是112
&a[0]+1
:地址移动一个元素的大小移动了四个字节,地址是0x1115
&a+1
:移动了整个数组的大小,移动了12个字节,地址是0x111d
二维整型数组
二维整型数组的定义格式
定义类型:类型名 数组名[ 行表达式 ][ 列表达式];行与列用常量表达式。
int arr[3][2];
arr
:是二维数组的名字,它是常量,也是二维数组的首地址;
3
:它有三行
2
:它有两列
注:一个二维数组,在本质上是有多个一维数组构成。(每个一维数的大小必须相同)
二维整型数组成员赋值
把二维数组看作一维数组赋值
int arr[3][2] = {1,2,3,4,5,6};
把二维数组看作二维维数组赋值
int arr[3][2] = {{5,},{6,},{7,8}}
二维字符数组
二维字符数组定义格式
char arr[10][10]
二维字符数组赋初值
将二维字符数组看作一维数组赋值
char a[3][3] = {'h','e','l','l','o'};
将二维字符数组当成二维数组赋值
char a[3][3] = {{'h','e',},{'l','l','o'},};
对二维数组赋初值的时候可以缺省行成员(不能缺省列成员)
char a[][3] = {{'h','e',},{'l','l','o'}};
对二维数组赋值字符串
char a[][10] = {"ni","hao","beijing"};
二维数组地址加1问题
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
假如二维数组的首地址是0x1111
&a[0][0]
:它是二维数组首个元素的地址,它的地址值是0x1111
a[0]
:第0行的地址,它的地址值是0x1111
&a
:对二维数组取地址,它的地址值是0x1111
&a[0][0]+1
:移动了4字节
a[0]+1
:移动4字节
&a[0]+1
:移动了16字节
a+1
:移动了16字节
&a+1
:移动了48字节
多维数组
C 语言支持多维数组。多维数组声明的一般形式如下:
type name[size1][size2]...[sizeN]; 例如,下面的声明创建了一个三维整型数组: int threedim[5][10][4];
注意:可以创建任意维度的数组,但是一般情况下,我们创建的数组是一维数组和二维数组。
由于一般使用一维数组或二维数组,在这里多维数组我们就不详细介绍了;
本节完!
下一节我们会详细介绍c语言中很重要的部分,也是c语言中的重难点 "指针"!http://t.csdnimg.cn/EbhMG
有问题或反馈请联系邮箱z1600306511@163.com