c语言指针、数组、函数做函数参数详解

用指针做参数

#include <stdio.h>
void swap(int *a, int* b) {
    int t = *a;
    *a = *b;
    *b = t;
}
int main() {
    int a = 3, b = 4;
    swap(&a, &b);
    printf("%d %d", a, b);
    return 0;
} 

数组作为参数和返回值

int sum(int a[]) {
    int ans = 0;
    for (int i = 0; i < sizeof(a); i++) {
        ans += a[i]
    }
    return ans;
}

这个函数是错误的,因为sizeof(a)无法得到数组的大小。
当把数组作为参数传递给函数时,实际上只有数组的首地址作为指针传递给了函数。换句话说,在函数定义中的int a[]等价于int *a。在只有地址信息的情况下,是无法知道数组理由多少个元素的。
正确的做法是加一个参数,即数组元素的个数。

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

在上面的代码中,直接把参数a写成了int *a,暗示a实际上是一个地址。在函数调用时a一定非要传递一个数组,例如:

int main() {
    int a[] = {1, 2, 3, 4};
    printf("%d\n", sum(a+1, 3));
    return 0;
} 

总结:
以数组为参数调用函数时,实际上只有数组首地址传递给了函数,需要另加一个参数表示元素个数。除了把数组首地址本身作为实参外,还可以利用指针加减法把其他元素的首地址传递给函数。
一般地,若p是指针,k是正整数,则p+k就是指针p后面第k个元素,p-k就是p前面的第k个元素,而如果p1和p2是类型相同的指针,则p2-p1是从p1到p2的元素个数(不含p2)。

计算左闭右开区间内的元素和(两种写法)
int sum(int *begin, int *end) {
    int n = end - begin;
    int ans = 0;
    for (int i = 0; i < n; i++) {
        ans += begin[i]; 
    }
    return ans;
}

int sum(int *begin, int *end) {
    int ans = 0;
    for (int *p = begin; p != end; p++) {
        ans += *p; 
    }
    return ans;
}

把函数作为函数的参数

古老的密码

问题描述
给定两个长度相同且不超过100的字符串,判断是否能把其中一个字符串的各个字母重排,然后对26个字母做一个一一映射,使得两个字符串相同。例如JWPUDJSTVP重排后可以得到WJDUPSJPVT,然后把每个字母映射到它的前一个字母(B->A, C->B, …, Z->Y, A->Z),得到VICTORIOUS。输入两个字符串,输出YES或者NO。

C语言的stdlib.h中有一个叫qsort的库函数,实现了著名的快速排序算法。它的声明是这样的:

void qsort (void *base, size_t num, size_t size, int (*comparator)(const void *, const void *));

前三个参数不难理解,分别是待排序的数组起始地址、元素个数和每个元素的大小。最后一个参数比较特别,是一个指向函数的指针,该函数应当具有这样的形式:

int cmp(const void *, const void *) {...}

这里得指针是指向常数的“万能”的指针:const void *,它可以通过强制类型转化变成任意类型的指针。对于本题来说,排序的对象是整型数组,因此要这样写:

int cmp(const void *a, const void *b) {
    return *(int *)a - *(int *)b;
}

先把参数a和b转化为真实的类型,然后让cmp函数当a<ba=ba>b时分别返回负数、0和正数即可。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值