【指针】02.指针与函数、结构体指针

【嵌入式八股】一、语言篇(本专栏)https://www.nowcoder.com/creation/manager/columnDetail/mwQPeM

【嵌入式八股】二、计算机基础篇https://www.nowcoder.com/creation/manager/columnDetail/Mg5Lym

【嵌入式八股】三、硬件篇https://www.nowcoder.com/creation/manager/columnDetail/MRVDlM

【嵌入式八股】四、嵌入式Linux篇https://www.nowcoder.com/creation/manager/columnDetail/MQ2bb0

指针与函数

函数传参

传入参数:

1. 指针作为函数参数。

2. 同常有const关键字修饰。

3. 指针指向有效区域, 在函数内部做读操作。

传出参数:

1. 指针作为函数参数。

2. 在函数调用之前,指针指向的空间可以无意义,但必须有效。

3. 在函数内部,做写操作。

4。函数调用结束后,充当函数返回值。

传入传出参数:

1. 指针作为函数参数。
1. 在函数调用之前,指针指向的空间有实际意义。

3. 在函数内部,先做读操作,后做写操作。 4. 函数调用结束后,充当函数返回值。

19.使用指针传递大容量参数

在C语言中,当函数参数较大时,为了避免传递复制数据导致内存开销较大,可以使用指针来传递参数。下面是使用指针传递大容量参数的示例:

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

void func(int *array, int size) { // 定义函数,传递指针和数组大小
    int i;
    for (i = 0; i < size; i++) {
        printf("%d ", array[i]); // 输出数组中的元素
    }
    printf("\n");
}

int main() {
    int size = 1000000; // 声明数组大小
    int *array = (int *)malloc(size * sizeof(int)); // 动态分配内存,创建数组

    // 初始化数组
    int i;
    for (i = 0; i < size; i++) {
        array[i] = i;
    }

    func(array, size); // 通过指针传递参数

    free(array); // 释放内存
    return 0;
}

在上述代码中,我们首先使用malloc()动态分配了一个包含1000000个整型元素的数组。然后在main()函数中初始化数组,并通过指针调用func()函数来访问数组中的元素。在func()函数中,我们使用了指针*array来访问数组中的元素,使用size参数指定了数组的大小。

函数中的形参定义的是一个int 型指针,那么传入的就需要是一个地址,可以是数组名,也就是数组的首地址,可以是对一个数据取地址&a,然后函数内使用就是array[1]或*(array+1),或 *a

需要注意的是,在使用指针传递参数时,需要确保指针指向的内存区域是有效的,并且在使用完毕后需要释放内存,以免造成内存泄漏。

20.使用指针传递输出(多个)参数

一般加了const就是传递参数或数组的;不加就是要返回数据的

在C语言中,可以使用指针来传递输出参数。指针指向的变量在函数内部被修改后,可以通过指针返回到调用者的代码中。下面是使用指针传递输出参数的示例:

#include <stdio.h>

void func(const int *a, const int *b, int *sum, int *diff) {
    *sum = *a + *b; // 计算a和b的和,通过指针返回
    *diff = *a - *b; // 计算a和b的差,通过指针返回
}

int main() {
    int a = 10, b = 5, sum, diff; // 定义变量

    func(&a, &b, &sum, &diff); // 通过指针传递参数

    printf("sum=%d, diff=%d\n", sum, diff); // 输出结果

    return 0;
}
21.交换两个数
#include <stdio.h>
void swap(int *x,int *y)  //x=&a,y=&b 值拷贝(实参 &a,&b 拷贝给形参x,y),这里拷贝的是地址
{
	//通过的地址,间接找到变量的内容,进行交换
	int temp;
	temp =*x;
	*x=*y;
	*y = temp;
}	

int main()    
{    
   int a=3,b=4;
   swap(&a,&b); //通过传递地址,来交换指向的内容
                //实参是地址
   printf("a=%d,b=%d\n",a,b); 	
   return 0;    
} 

指针函数和函数指针

22.函数指针和指针函数有什么区别?

函数指针 如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。

int(*p)(int, int);

这个语句就定义了一个指向函数的指针变量 p。首先它是一个指针变量,所以要有一个“* ”,即(* p); 其次前面的 int 表示这个指针变量可以指向返回值类型为 int 型的函数;后面括号中的两个 int 表示这个指针变量可以指向有两个参数且都是 int 型的函数。所以合起来这个语句的意思就是:定义了一个指针变量 p,该指针变量可以指向返回值类型为 int 型,且有两个整型参数的函数。p 的类型为 int(*) (int,int) 。 我们看到,函数指针的定义就是将“函数声明”中的“函数名”改成“(指针变量名)”。但是这里需要注意的 是:“(指针变量名)”两端的括号不能省略,括号改变了运算符的优先级。如果省略了括号,就不是定义函数指针而是一个函数声明了,即声明了一个返回值类型为指针型的函数。 最后需要注意的是,指向函数的指针变量没有 ++ 和 -- 运算。

# include <stdio.h> 
int Max(int x, int y) 
{
	return x>y?x:y; 
} 
int main(void) {
	int(*p)(int, int);               //定义一个函数指针 
	int a, b, c; 
	p = Max;                         //把函数Max赋给指针变量p, 使p指向Max函数 
    printf("please enter a and b:"); 
    scanf("%d%d", &a, &b); 
    
    c = (*p)(a, b);                  //通过函数指针调用Max函数 
    //或者c=p(a, b); 【两种函数指针的调用方式】
    printf("a = %d\nb = %d\nmax = %d\n", a, b, c); 
    return 0;
}

linux内核中的file_operation结构体中就是一大堆函数指针,具体操作函数编写后注册即可,用户在文件系统中调用系统调用函数的名字都是函数指针的名字。

struct file_operations { 
  struct module *owner;//拥有该结构的模块的指针,一般为THIS_MODULES  
   loff_t (*llseek) (struct file *, loff_t, int);//用来修改文件当前的读写位置  
   ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);//从设备中同步读取数据   
   ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);//向设备发送数据  
   ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);//初始化一个异步的读取操作   
   ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);//初始化一个异步的写入操作   
  int (*readdir) (struct file *, void *, filldir_t);//仅用于读取目录,对于设备文件,该字段为NULL   
   unsigned int (*poll) (struct file *, struct poll_table_struct *); //轮询函数,判断目前是否可以进行非阻塞的读写或写入   
  int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); //执行设备I/O控制命令   
  long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); //不使用BLK文件系统,将使用此种函数指针代替ioctl  
  long (*compat_ioctl) (struct file *, unsigned int, unsigned long); //在64位系统上,32位的ioctl调用将使用此函数指针代替   
  int (*mmap) (struct file *, struct vm_area_struct *); //用于请求将设备内存映射到进程地址空间  
  int (*open) (struct inode *, struct file *); //打开   
  int (*flush) (struct file *, fl_owner_t id);   
  int (*release) (struct inode *, struct file *); //关闭   
  int (*fsync) (struct file *, struct dentry *, int datasync); //刷新待处理的数据   
  int (*aio_fsync) (struct kiocb *, int datasync); //异步刷新待处理的数据   
  int (*fasync) (int, struct file *, int); //通知设备FASYNC标志发生变化   
  int (*lock) (struct file *, int, struct file_lock *);   
  ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);   
  unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);   
  int (*check_flags)(int);   
  int (*flock) (struct file *, int, struct file_lock *);  
  ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);  
  ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);   
  int (*setlease)(struct file *, long, struct file_lock **);   
};
struct file_operations fops = {
    .read = device_read,
    .write = device_write,
    .open = device_open,
    .release = device_release
};

指针函数 首先它是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有“函数返回值”,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。

类型名 *函数名(函数参数列表);

其中,后缀运算符括号“()”表示这是一个函数,其前缀运算符星号“*”表示此函数为指针型函数,其函数值为指针,即它带回来的值的类型为指针,当调用这个函数后,将得到一个“指向返回值为…的指针(地址),“类型名”表示函数返回的指针指向的类型”。 “(函数参数列表)”中的括号为函数调用运算符,在调用语句中,即使函数不带参数,其参数表的一对括号也不能省略。其示例如下:

int *pfun(int, int);

由于“*”的优先级低于“()”的优先级,因而pfun首先和后面的“()”结合,也就意味着,pfun是一个函数。 即:

int *(pfun(int, int));

接着再和前面的“*”结合,说明这个函数的返回值是一个指针。由于前面还有一个int,也就是说,pfun 是一个返回值为整型指针的函数。

#include <stdio.h> 
float *find(float(*pionter)[4],int n);//函数声明 
int main(void) {
static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}}; 
    float *p; 
    int i,m; 
    printf("Enter the number to be found:"); 

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

【嵌入式八股】一、语言篇 文章被收录于专栏

查阅整理上千份嵌入式面经,将相关资料汇集于此,主要包括: 0.简历面试 1.语言篇【本专栏】 2.计算机基础 3.硬件篇 4.嵌入式Linux (建议PC端查看)

全部评论

相关推荐

头像
11-26 15:46
已编辑
中南大学 后端
字节国际 电商后端 24k-35k
点赞 评论 收藏
分享
hso_:哈哈哈哈哈哈我没offer一样在同一道题开喷了
投递深圳同为数码等公司10个岗位
点赞 评论 收藏
分享
点赞 2 评论
分享
牛客网
牛客企业服务