首页 > 其他分享 >大话C语言:第34篇 指针与函数的关系

大话C语言:第34篇 指针与函数的关系

时间:2024-08-02 17:53:14浏览次数:17  
标签:返回 函数 指向 int 大话 C语言 函数指针 34 指针

1 指针作为函数的参数

指针作为函数的参数,语法格式:

返回数据类型 函数名(数据类型 *指针变量1, ..., 数据类型 *指针变量1)

注意,指针变量的数据类型可以为任何数据类型,包括基本数类型和自定义数据类型

代码示例:

void swap(int *ptr1,int *ptr2)
{
    // 提前保存ptr1指向对象内容
    int temp = *ptr1;
    // ptr2指向的变量的值,给ptr1指向的变量赋值
    *ptr1=*ptr2;
    *ptr2=temp;
}
int main()
{
    int num1 = 15;
    int num2 = 20;
    swap(&num1,&num2);
    
    printf("num1=%d num2=%d\n",num1,num2);
    
    return 0;
}

注意,指针作为函数参数,称为地址传递方式;与之相对应的称为值传递,它们之间有着明显区别:

  • 值传递:值传递是直接将参数的值复制到函数内部的参数中。在函数执行完毕后,这个复制的值可能会被改变,但原始变量的值并不会受到影响。这是因为函数内部操作的是这个值的副本,而不是原始变量本身。

  • 地址传递是传递参数的地址(或引用)到函数中。这意味着函数内部操作的是原始变量的内存地址,因此任何在函数内部对这个地址的修改都会直接影响到原始变量。

其中,值传递的优缺点分别是:

  • 优点:简单、安全,因为函数内部的操作不会影响到函数外部的变量。

  • 缺点:如果传递的参数是大型对象或数据结构,那么复制这些值可能会消耗大量的时间和内存。

地址传递的优缺点分别是:

  • 优点:对于大型对象或数据结构,地址传递可以避免复制值带来的性能开销,因为它只需要传递一个地址(或引用)。

  • 缺点:由于函数内部可以直接修改原始变量,这可能导致函数外部的变量被意外地改变,从而增加了出错的可能性。因此,使用地址传递时需要更加小心。

值传递代码示例:

void swap(int num1,int num2)
{
    int temp = num1;
    num1 = num2;
    num2 = temp;
}
int main()
{
    int num1 = 15;
    int num2 = 20;
    swap(num1,num2);
    
    printf("num1=%d num2=%d\n",num1,num2);
    
    return 0;
}

2 指针作为函数返回值

指针可以作为函数的返回值。这通常用于动态分配内存并返回指向该内存的指针,或者返回指向某个已存在对象的指针。语法格式:

// 函数返回类型的指针  
数据类型* 函数名(参数列表);

代码示例:

#include <stdio.h>  
#include <stdlib.h> 

// 函数返回一个整数的指针  
int* createArray(int size) 
{  
    // 动态分配一个整数数组  
    int* array = (int*)malloc(size * sizeof(int));  
    if (array == NULL) 
    {  
        // 内存分配失败,返回NULL  
        return NULL;  
    }  
      
    // 初始化数组(可选)  
    for (int index = 0; index < size; ++index) 
    {  
        array[index] = 0;  
    }  
      
    // 返回指向数组的指针  
    return array;  
}  
  
int main() 
{  
    // 调用函数创建数组  
    int* myArray = createArray(10);  
    if (myArray != NULL) 
    {  
        // 使用数组...  
        for (int index = 0; index < 10; ++index) 
        {  
            printf("%d ", myArray[index]);  
        }  
        printf("\n");  
          
        // 释放内存  
        free(myArray);  
    } 
    else 
    {  
        printf("内存分配失败!\n");  
    }  
      
    return 0;  
}

注意,返回地址的时候,地址指向的内存的内容不能释放。如果返回的指针指向的内容已经被释放了,返回这个地址,也没有意义了。例如,

#include <stdio.h>  
  
// 错误的示例:返回指向局部变量的指针  
int* GetLocalVar() 
{  
    int localVar = 42; // 局部变量  
    
    return &localVar; // 返回指向局部变量的指针  
}  
  
int main() 
{  
	// 获取指向局部变量的指针  
    int* ptr = GetLocalVar();
    
    // 尝试访问该值,但此时内容可能已失效  
    printf("The value is: %d\n", *ptr); 
    
    return 0;  
}

上述函数返回了指向局部变量的指针,那么这是非常危险的,因为局部变量在函数返回后其存储空间可能会被覆盖或释放,导致指针指向的内容失效。

3 函数指针

函数指针是一个特殊的指针,它指向某个函数的入口地址,使得程序可以通过该指针变量调用该函数。函数指针本身是一种数据类型,其类型与所指向函数的返回值类型和参数类型有关。函数指针的定义方式类似于变量的定义,只不过需要加上括号和星号。

函数指针定义,语法格式

// 先定义函数
返回类型 函数名(形参列表);
// 定义函数指针
返回类型 (*函数指针名)(形参列表);
// 函数指针指向函数
函数指针名 = 函数名;

代码示例:

#include <stdio.h>  
  
void print_number_one(int num) 
{  
    printf("Function 1: The number is %d\n", num);  
}  
  
void print_number_two(int num) 
{  
    printf("Function 2: The number is %d\n", num);  
}

int main()
{  
	void (*function_pointer)(int);
	
    // 指向第一个函数  
    function_pointer = print_number_one;  
    function_pointer(10); // 输出:Function 1: The number is 10  
  
    // 指向第二个函数  
    function_pointer = print_number_two;  
    function_pointer(20); // 输出:Function 2: The number is 20  
  
    return 0;  
}

函数指针在C/C++编程语言中非常有用,它们可以用于多种情况:

  • 声明函数指针:函数指针的声明格式为“返回类型(*指针变量名)(参数类型列表)”。例如,int (*p)(int, int)表示p是一个指向返回类型为int,参数类型为int, int的函数指针。

  • 定义函数指针:定义函数指针时,需要将其指向具体的函数。例如,如果有一个函数int add(int a, int b) { return a + b; },那么可以通过int (*p)(int, int) = add;将函数指针p指向函数add。

  • 函数指针作为参数:函数指针还可以作为函数的参数,这种用法通常用于回调函数。这样,可以通过一个函数调用不同的回调函数,实现不同的操作。

  • 函数指针数组:函数指针还可以放在数组中,形成函数指针数组。

4 函数指针数组

函数指针数组是一个存储了多个函数指针的数组。每个数组元素都是一个指向函数的指针,这些函数具有相同的返回类型和参数列表。语法格式:

返回数据类型 (*数组名[])(参数列表);

代码示例:

#include <stdio.h>  
  
// 定义两个函数,它们将被存储在函数指针数组中  
void PrintFun1() 
{  
    printf("调用的是PrintFun1\n");  
}  
  
void PrintFun2() 
{  
    printf("调用的是PrintFun2\n");  
}  
  
int main() 
{  
    // 定义函数指针数组,可以存储两个返回类型为void、没有参数的函数指针  
    void (*funPtrArr[])() = {PrintFun1, PrintFun2};  
      
    // 通过函数指针数组调用函数  
    funPtrArr[0](); // 输出: Function 1 called  
    funPtrArr[1](); // 输出: Function 2 called  
      
    return 0;  
}

注意,函数指针数组中的所有函数指针必须指向具有相同返回类型和参数列表的函数。如果尝试将具有不同签名(即返回类型或参数列表不同)的函数指针存储在同一个数组中,编译器将会报错。

标签:返回,函数,指向,int,大话,C语言,函数指针,34,指针
From: https://blog.csdn.net/whccf/article/details/140876914

相关文章

  • c语言学习 volatile __attribute__ const
    1volatile在C语言中,volatile是一个类型修饰符,用于告诉编译器某个变量的值可能会被外部因素改变,从而避免编译器对该变量进行优化。这在多线程编程或硬件编程中非常重要。用法volatileintmyVar;何时使用volatile硬件寄存器:当变量映射到某个硬件寄存器。中断服务例......
  • [lnsyoj2234/luoguP9323]玩具设计
    题意原题链接给定一个\(n\)个点的无向图,你可以进行不超过\(max\_ops\)次查询操作\(\text{Connected}(x,a,b)\),每次操作可以查询在版本\(x\)中,\(a,b\)两个点之间是否连通,若连通,则返回当前版本号,否则新建一个版本,在该新版本中将这两个点之间连一条边,并返回新版本的版本号......
  • 学习C语言的第4天--运算符与流程控制
    今日目标了解各种运算符及其用法。掌握条件语句和循环语句的使用。每日练习目录今日目标运算符1.算术运算符2.关系运算符3.逻辑运算符4.位运算符5.赋值运算符6.其他运算符条件运算符(三元运算符)指针运算符逗号运算符流程控制1.条件语句if语句if-else语句......
  • c语言数据结构-单链表
    typedefstructLNode{   Elemtypedata;   structLNode*next;}LNode,*Linklist;//初始化单链表(不带头节点)boolInitList(LinkList&L){   L=NULL;   returntrue;}插入boolListInsert(LinkList&L,inti,Elemtypee){   if(i<1)  ......
  • C语言:进制
    简介说到进制,我们最为熟知的便是十进制,今天我们来说一下二进制,八进制和十六进制。所谓二进制,就是逢二进一,同样的,八进制和十六进制也就是逢八进一,逢十六进一。注意:十六进制中10到15用ABCDEF表示。举几个数字作为例子:十进制二进制八进制十六进制111110101012A10011001001446......
  • 题解:CF634A Island Puzzle
    CF634AIslandPuzzle题解分析由于我们仅能移动\(0\),所以其它数字的相对顺序较原来应该是不变的,所以我们从环中删除\(0\)再判断相对位置即可。还有需要注意的是本题是一个环,找到末尾需要用取模操作回到开头继续比较。示例代码#include<bits/stdc++.h>usingnamespacest......
  • 数据结构C语言---文件的加密和解密
    本篇的主要目的是利用所学的数据结构的知识对一个任意文件进行加密和解密。在文件加密过程中,常用的数据结构包括哈希表、树结构(如二叉搜索树、哈夫曼树)、堆、链表等。选择合适的数据结构取决于加密算法的需求和特性。选择合适的加密算法和数据结构对保障数据安全至关重要。常......
  • 从零开始学嵌入式技术之C语言09:数组
    一:数组的概念(1)概念        数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个标识符命名,并通过编号(索引,亦称为下标或角标)的方式对这些数据进行统一管理。    数组名:本质上是一个标识符常量,命名需要符合标识符规范。元素:同一个数组中的元素必须是相......
  • 深入理解C语言中的结构体
    目录引言一.结构体的基本概念1.结构体的声明2.结构体变量的创建和初始化3.结构体成员访问操作符4.结构体的特殊声明1.匿名结构体2.嵌套结构体3.结构体自引用4.typedef声明二、结构体内存对⻬1.对⻬规则2.为什么存在内存对⻬?3.修改默认对齐数三、结构体......
  • 代码随想录算法训练营第二十五天|134. 加油站、135. 分发糖果、860.柠檬水找零、406.
    写代码的第二十五天继续贪心!!gogogo!134.加油站思路贪心算法总让我有种脑子知道每次怎么计算,但是写不出来,也想不出贪心贪在哪里了,就只是觉得应该这么做。。。。。本题中大家可以按照自己的计算方法一步一步模拟一下这个过程,然后会发现其实每次都是要计算每站剩余的油量,......