C语言基础7函数基本用法_c语言函数-程序员宅基地

技术标签: c语言  物联网  开发语言  

前言重点关注传参的方式,指针数组、二维数组等加深理解

目录

一、函数基础概念、说明和使用

1、函数一般形式

2、函数的说明

3、函数的使用

4、设计函数3个步骤

总结

二、函数的参数传递

1、全局变量

2、复制传递方式

3、地址传递方式

总结:

三、数组在函数间传参

1、全局数组传递方式

2、复制传递方式

3、地址传递方式

总结


一、函数基础概念、说明和使用

1、函数一般形式

-函数是一个完成特点功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值
-一般形式如下:
<数据类型><函数名称>(<形式参数说明>)
{
    语句序列;
    return[<表达式>)];
}

<数据类型>是整个函数的返回值类型。return[(<表达式>)]语句中表达式的值,要和函数的<数据类型>保持一致。如无返回值应该写为void型
<形式参数说明>是逗号”,”分隔的多个变量的说明形式
 {<语句序列> }大括弧对,称为函数体;<语句序列>是大于等于零个语句构成的
 

2、函数的说明

函数的说明就是指函数原型。 其中,<形式参数说明>可以缺省说明的变量名称,但类型不能缺省例如,double  Power(double x, int n) ;double  Power(double, int);
 

3、函数的使用

函数的使用也叫函数的调用,形式如下: 函数名称(〈实际参数〉)实参就是在使用函数时,调用函数传递给被调用函数的数据。需要确切的数据函数调用可以作为一个运算量出现在表达式中,也可以单独形成一个语句。对于无返回值的函数来讲,只能形成一个函数调用语句。

4、设计函数3个步骤

例:定义求x^n(x是实数,n为正整数)

(1)取函数名称power

(2)参数类型double x、int n

(3)返回值double

(4)函数实现

#include <stdio.h>

double power(double x,int n); //函数的申明

int main(int argc, const char * argv[])
{
        //const char * argv[] = {"./a.out","192.168.1.5","8080"};
        double res;
        res = power(2,8);    //函数的调用
        printf("res=%lf\n", res);

        return 0;
}

double power(double x,int n){  //函数的实现
        int r = 1,i;
        for(i = 1; i <= n; i++)
                r = x * r;
        return r;
}

总结

主要介绍函数的基础知识,包括函数的概念、函数的说明及函数的使用。

思考什么叫函数的说明,如何进行函数的说明?
答:函数必须先声明,后调用。提前声明函数,这样编译器就可以一次执行(即只读取一次代码)。还有之前的机器内存比较小,这样的编写能让编译器能够在内存资源有限的机器上运行,并且帮我们进行一定的语法检查。

使用库函数时,为什么引入头文件,有没有别的替代写法?

答:.i文件就是把头文件的一些定义函数展开,目的头文件里面有函数的说明。如果不需要头文件,可以自己写,但是很麻烦。

二、函数的参数传递

函数之间的参数传递方式:
-全局变量
-复制传递方式
-地址传递方式

1、全局变量

全局变量 
-全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的
-全局变量一经定义后就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会受到影响。不建议使用

2、复制传递方式

复制传递方式
-调用函数将实参传递给被调用函数,被调用函数将创建同类型的形参并用实参初始化
-形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。

 

第一种情况相当于 double a = x;x是实参,a是形参

不能实现两个数据的交换,因为也叫值传递。

3、地址传递方式

-按地址传递,实参为变量的地址,而形参为同类型的指针
-被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)

地址传递也叫指针传递。

通过两个程序来说明实际应用

编程:写一个函数,实现两个数据的交换

#include <stdio.h>

void swap(int * x,int * y);

int main(int argc, const char * argv[])
{
        int a = 5,b = 10;
        printf("a=%d,b=%d\n", a, b);
        swap(&a,&b);
        printf("a=%d,b=%d\n", a, b);
        return 0;
}

void swap(int * x,int * y){
        int temp;
        temp = *x;
        *x = *y;
        *y = temp;
}
//结果         

a=5,b=10
a=10,b=5

编写一个函数,统计字符串中小写字母的个数,并把字符串中的小写字母转化成大写字母。
注意:有些需求不需要改变原始数据,就加const更严谨,别人知道一定不会改变数组。

思路:a-z的十进制asc码值是97-122之间,判断指针变量指向的值是否小写范围内,如果是小写计数变量+1并且指针指向的值-32转为大写字母。

#include <stdio.h>

int upper(char * ch);                         //函数的申明

int main(int argc, const char * argv[])
{
        char array[] = "Hello World!";        //定义字符串,如果是char * s = "hello"是不行的,因为字符串常量不能修改
        int n = 0;
        printf("array=%s\n", array);          //调用前打印
        n =  upper(array);                    //函数调用
        printf("array=%s,n=%d\n", array, n);  //调用后打印
        return 0;
}

int upper(char * ch){                            //函数实现
        int c = 0;                               //计数变量
        while(*ch != '\0'){                      //字符串指针不等于'\0',判断是否小写,是小写计数+1并且-32转为大写字母
                if((*ch >= 97) && (*ch <= 122)){
                        c++;
                        *ch = *ch -32;
                }
                ch++;
        }
        return c;                               //返回计数值,字符串已经通过指针地址修改保存到主函数中
}


//结果
array=Hello World!
array=HELLO WORLD!,n=8

总结:

主要介绍了函数的参数传递,包括全局变量、复制传递和地址传递三种方式思考


-复制传递和地址传递方式有什么区别?

答:  需要改变实参就要用地址传递

-如何编程可以实现地址传递方式也不能改变实参?

参数前加const,例如  int upper(const char * ch)。(在C语言基础6的const和void文章末提到过)

三、数组在函数间传参

1、全局数组传递方式

2、复制传递方式

复制传递方式
-参数为数组的指针,形参为数组名(本质是一个指针变量)

编程案例:编写函数,计算一个一维整型数组的所有元素的和

思路:这里数组的个数不能像字符串一样,一般需要用户给点,sizeof不能定义在函数内部。

#include <stdio.h>

int Array_Sum(int data[], int n );                      //也可以写成 * data

int main(int argc, const char * argv[])
{
        int array[20] = {1,2,3,4,5,6,7,8,9,10};
        int sum;
        sum = Array_Sum(array, sizeof(array)/sizeof(int));
        printf("sum=%d\n", sum);
        return 0;
}

int Array_Sum(int data[], int n){
        int sum = 0;
        int i = 0;
        for(i = 0; i < n; i++){
                sum = data[i] + sum;
        }
        return sum;
}

//结果

55

3、地址传递方式

实参为数组的指针,形参为同类型的指针变量。

编程案例:删除字符串中的空格

w a u \0

p != null

p != null p != null p != null p != null p = null
*p != ' ' *p = ' ' *p != ' ' *p = ' ' *p != ' '

p++

p++ p++ p++ p++

*ch = *p

ch++

*ch = *p

ch++

*ch = *p

ch++

*ch = '\0'
#include <stdio.h>

void Del_Space(char * ch);

int main(int argc, const char * argv[])
{
        char s[] = "who are you?";
        Del_Space(s);
        printf("%s\n", s);
        return 0;
}

void Del_Space(char * ch){

        char * p;
        p = ch;
        while(*p != '\0'){            //等同于 while(*p)
                if(*p == ' '){
                        p++;
                }
                else{
                        *ch = *p;
                        ch++;
                        p++;
                }
        }
        *ch = '\0';              //需要注意\0要写过来
}
        

总结

主要介绍数组作为参数在函数间的传递方式,如果是字符串的只需要传指针就可以了,如果是比如int型的数组,需要传指针还需要传一个数组个数。

推导,如果是二维数组传参怎么传?

答: 定义函数是 int fun(int *a,int n)

调用函数也是直接 fun(a,n);

#include <stdio.h>

void Fun(int ** arr ,int n,int m);

int main(int argc, const char * argv[])
{
        int a[][4] = {
   {1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
        printf("%d %d\n",sizeof(a)/sizeof(a[0]),sizeof(a[0])/sizeof(int));  //打印计算行和列
        Fun((int **)a,sizeof(a)/sizeof(a[0]),sizeof(a[0])/sizeof(a[0][0]));
        return 0;
}

void Fun(int ** arr,int n, int m){
        int i,j =0;
        for(i = 0; i < n; i++){
                for(j = 0; j < m; j++){
                                printf("%2d ",*(int *)(arr+i * n+j));   //通过线性计算
                }
                puts("");
        }
}
                
//剩余2种方法
void Fun2(int arr[3][2],int len,int width){
    for (int i = 0; i<len; i++) {
        for (int j = 0; j<width; j++) {
            printf("%d \n",arr[i][j]); //(OK)
        }
    }
}
void Fun3(int (*arr)[2],int len,int width){
    for (int i = 0; i<len; i++) {
        for (int j = 0; j<width; j++) {
            printf("%d \n",arr[i][j]); //ok
        }
    }
}

void Fun4(int* (arr[3]),int len,int width){
    for (int i = 0; i<len; i++) {
        for (int j = 0; j<width; j++) {
//            printf("%d \n",arr[i][j]); //(X)
             printf("%d \n",(arr+2*i)[j]); //(X)
        }
    }
}

指针数组作为参数在函数间传参,如何编程?

类似于一位普通数组的传递方法,将数组名作为数组的首元素地址进行实参传递,在形参接实参的时候要注意指针数组的类型是二级指针,所以要用二级指针,要想在函数内访问指针数组的成员,用%s方式 ,后跟arr[i]的方式,arr[i]中存放的就是每个字符串的地址。

#include<stdio.h>

void print_arr(char **buf, int n)
{
    int i=0;
    for(i=0;i<n;i++)
        printf("%s\n",buf[i]);
}

int main(int argc, char *argv[])
{
    char *buf[3]={“apple”,“orange”,“banana”,NULL};
    int n=sizeof(buf)/sizeof(buf[0]);
    print_arr(buf,n);

    return 0;
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_60718520/article/details/127194449

智能推荐

Python自然语言处理-带你玩转NLTK库常见操作_nltk.corpus.words.words()-程序员宅基地

文章浏览阅读1.1k次,点赞3次,收藏13次。from nltk.book import * # 加载语料库text1.concordance('monstrous') # 搜索文本上下文text1.similar('monstrous') # 查找与monstrous拥有共同上下文的词text2.common_contexts(['monstrous','very'])text4.dispersion_plot(['America','citizen','democracy','freedom']) # 文中分布位置text3.gener._nltk.corpus.words.words()

【webrtc】Chrome和Firefox在SDP协商过程中,针对localhost的不同处理

mDNS(Multicast DNS,多播DNS)是一种基于DNS(域名系统)的协议,它允许局域网内的设备在没有传统DNS服务器的情况下相互发现和通信。mDNS使用组播技术,通过在局域网内发送广播消息来实现设备的发现和通信。它使用的默认端口是5353。mDNS的工作原理是,当一个设备加入到局域网中,如果它开启了mDNS服务,就会向局域网内的所有设备发送组播消息,告知自己的存在以及IP地址等信息。其他开启mDNS服务的设备接收到这些消息后,就可以响应并提供自己的信息。

机器学习笔试面试超详细总结(二)_机器学习算法笔试-程序员宅基地

文章浏览阅读7.6k次,点赞5次,收藏74次。51、概率和信息量的关系52、数据清理中,缺失值的处理方法53、统计模式分类问题54、语言模型0概率问题55、逻辑回归和多元回归分析的不同56、关于Word2Vec57、词向量58、二次准则函数的H-K算法比感知器的优势59、卷积之后特征图谱的大小60、矩阵计算效率61、数据过大时,那种梯度下降方法更好62、选择神经网络深度时,需要考虑哪些参数63、如何利用已有训..._机器学习算法笔试

Unity3D Camera设置结合OpenGL详细解读_unity配合opengles-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏5次。首先,总体概述。Unity里面的Camera是把渲染画面,最终呈现在屏幕上的最后一步操作。所有的渲染操作最终都要通过Camera在呈现。如果用OpenGL来实现,Camera做了一下几个事情。通过正交或是透视,剪裁平面,得到一个4x4的矩阵数据。这个矩阵就是,model-view-projection中的projection。所有物体的旋转R,平移T,缩放S,形成的矩阵数据_unity配合opengles

Python来计算 1,2,3,4 能组成多少个不相同且不重复的三位数?

我们今天的例子是 有 1,2,3,4 四个数字,它们能组成多省个互不相同且无重复的三位数?都分别是多少?

理解CSS中的sticky与fixed定位

在CSS中,和是两种常见的定位方式,它们可以让元素脱离文档流,并具有固定位置的效果。然而,它们在实际应用中有着不同的特点和使用场景。

随便推点

浅谈未定义行为(Undefined behavior)_计算机未定义行为-程序员宅基地

文章浏览阅读4.2k次。一、维基百科:在计算机编程中,未定义行为(英语:Undefined behavior)是指行为不可预测的计算机代码。这是一些编程语言的一个特点,最有名的是在C语言中。[1]在这些语言中,为了简化标准,并给予实现(根据我的理解,这里的“实现”指的是编译器)一定的灵活性,标准特别地规定某些操作的结果是未定义的,这意味着程序员不能预测会发生什么事。二、实例请看我在csdn的php发过的一_计算机未定义行为

获取webshell权限的45种方法_.net站点拿webshell-程序员宅基地

文章浏览阅读10w+次,点赞2次,收藏16次。1, 到GoogLe,搜索一些关键字,edit.asp? 韩国肉鸡为多,多数为MSSQL数据库! 2, 到Google ,site:cq.cn inurl:asp 3, 利用挖掘鸡和一个ASP木马. 文件名是login.asp 路径组是/manage/ 关键词是went.asp 用'or'='or'来登陆 4, 关键字:Co Net MIB Ver 1.0网_.net站点拿webshell

边缘设备接入华为云并在线进行模拟设备测试_边缘计算设备怎么接入云-程序员宅基地

文章浏览阅读5.1k次。此案例以一个灯的开关控制为演示(嵌入式点灯工程师)总体流程1.创建产品1.1 访问华为云 IoT 管理控制台华为云官网进入设备接入服务选择“产品”->“IoT 物联网”->“设备接入 IoTDA”;点击免费试用确认控制台为北京四1.2 模型定义​此处个人理解为对灯的属性和功能进行定义 产品->创建产品创建产品此时产品中出现刚创建的产品2.产品定义2.1 产品属性定义点击产品名称“LED_IOT”,进入产品详情页点击“模型定义”->“自_边缘计算设备怎么接入云

PD生成兼容Oracle、Mysql脚本-程序员宅基地

文章浏览阅读82次。mysqldate 改为 datetime->运行sql脚本Oracle"clustered"替换为空,即key(XX)->运行sql脚本转载于:https://www.cnblogs.com/vvonline/p/10215134.html..._pd转化oracle至mysql

七、四个步骤实现FFmpeg推流播放实战

nginx-http-flv-module的。# 添加RTMP服务。

Python基础:【扩展系列】Python对小程序或App进行自动化操作常用框架

Python基础:【扩展系列】Python对小程序或App进行自动化操作常用框架

推荐文章

热门文章

相关标签