一、形参的概念

C语言中形参和实参的概念——

形参(Formal Parameter)
  • 定义在函数声明和函数定义中的参数
  • 是函数接收外部数据的接口
  • 属于函数的局部变量,只在函数内部有效
二、实参的概念
实参(Actual Argument)
  • 调用函数时实际传入的参数
  • 可以是常量、变量或表达式
  • 必须与形参在类型、数量和顺序上匹配
三、参数传递方式
1. 值传递(Pass by Value)
  • 将实参的值复制给形参
  • 函数内对形参的修改不影响实参
  • C/C++默认的参数传递方式

代码语言:javascript

AI代码解释

void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 1, y = 2;
    swap(x, y);  // x和y的值不会改变
}
2. 指针传递(Pass by Pointer)
  • 传递变量的地址
  • 函数内可以通过指针间接修改实参的值
  • C语言常用的参数传递方式

代码语言:javascript

AI代码解释

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 1, y = 2;
    swap(&x, &y);  // x和y的值被交换
}
3. 引用传递(Pass by Reference)
  • C++特有
  • 形参是实参的别名
  • 函数内对形参的修改直接影响实参

代码语言:javascript

AI代码解释

void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 1, y = 2;
    swap(x, y);  // x和y的值被交换
}
四、数组作为参数
(一)一维数组

代码语言:javascript

AI代码解释

// 三种等效的声明方式
void func(int arr[]);
void func(int arr[10]);  // 10会被忽略
void func(int *arr);
(二)多维数组

代码语言:javascript

AI代码解释

// 第二维必须指定大小
void func(int arr[][10]);
void func(int (*arr)[10]);  // 指针数组
五、默认参数(C++)
  • 在函数声明中为形参指定默认值
  • 默认参数必须从右向左连续定义
  • 通常在头文件中声明默认值

代码语言:javascript

AI代码解释

void func(int a, int b = 10, int c = 20);

func(1);       // 等同于 func(1, 10, 20)
func(1, 2);    // 等同于 func(1, 2, 20)
六、函数重载(C++)
  • 函数名相同但参数列表不同
  • 参数类型、数量或顺序不同
  • 返回值类型不同不构成重载

代码语言:javascript

AI代码解释

void print(int a);
void print(double a);
void print(const char* str);
七、可变参数
  • C语言使用<stdarg.h>
  • C++11引入可变参数模板

代码语言:javascript

AI代码解释

#include <stdarg.h>
#include <stdio.h>

void printNumbers(int count, ...) {
    va_list args;
    va_start(args, count);
    
    for (int i = 0; i < count; i++) {
        int num = va_arg(args, int);
        printf("%d ", num);
    }
    
    va_end(args);
}

int main() {
    printNumbers(3, 1, 2, 3);
}
八、形参(形式参数)与实参(实际参数)的对比

C语言形参和实参的关系——

(一)基本概念对比

特性

形参(Formal Parameter)

实参(Actual Argument)

定义位置

函数声明和定义中

函数调用时传入

作用域

函数体内局部有效

函数调用前已存在的变量或表达式

生命周期

函数调用时创建,返回时销毁

取决于原变量/表达式的生命周期

必需性

函数签名必需部分

调用时必须提供(除非有默认参数)

(二)内存关系对比
1、值传递情况

代码语言:javascript

AI代码解释

void func(int param) {  // param是形参
    param = 100;
}

int main() {
    int arg = 10;      // arg是实参
    func(arg);          // 创建param副本
    // arg仍为10
}
  • 形参获得实参的独立副本
  • 修改形参不影响实参
2、指针传递情况

代码语言:javascript

AI代码解释

void func(int *param) {  // param是形参指针
    *param = 100;
}

int main() {
    int arg = 10;        // arg是实参
    func(&arg);          // 传递地址
    // arg变为100
}
  • 形参获得实参的地址副本
  • 通过指针可修改原实参
3、引用传递情况(C++)

代码语言:javascript

AI代码解释

void func(int &param) {  // param是形参引用
    param = 100;
}

int main() {
    int arg = 10;        // arg是实参
    func(arg);           // param是arg的别名
    // arg变为100
}
  • 形参是实参的别名
  • 修改形参直接修改实参
(三)典型差异(附带示例)
1、数组参数的特殊性

代码语言:javascript

AI代码解释

void arrayFunc(int arr[]) {  // 形参arr实际是指针
    sizeof(arr);             // 指针大小(如8字节)
}

int main() {
    int actualArr[10];
    sizeof(actualArr);       // 数组大小(如40字节)
    arrayFunc(actualArr);    // 数组退化为指针
}
  • 数组作为形参时会退化为指针
  • 实参仍保持数组特性
2、默认参数处理

代码语言:javascript

AI代码解释

void func(int a = 10);  // 默认值在声明中指定

int main() {
    func();             // 使用默认实参10
    func(20);          // 提供显式实参
}
  • 默认值属于形参声明部分
  • 调用时可省略对应实参
3、函数重载解析

代码语言:javascript

AI代码解释

void print(int a);     // 重载版本1
void print(double a);  // 重载版本2

int main() {
    print(10);         // 根据实参类型选择版本1
    print(10.0);       // 根据实参类型选择版本2
}
  • 重载决策基于实参与形参的匹配程度
(四)总结两者的关键区别
1、创建时机
  • 形参:函数调用时创建
  • 实参:调用前已存在
2、内存关系
  • 值传递:完全独立
  • 指针传递:共享同一内存地址
  • 引用传递:完全共享内存
3、类型处理
  • 实参到形参可能发生隐式类型转换

代码语言:javascript

AI代码解释

void func(double d);
func(10);  // int实参转换为double形参
4、数组处理
  • 形参中的数组总是退化为指针
  • 实参保持原始数组类型(除非已退化为指针)
5、C++特有的特性
  • 引用参数
  • 默认参数
  • 函数重载
  • 右值引用(C++11)
九、C/C++形参和实参的对比
基本概念对比

特性

C语言

C++

形参定义

函数声明和定义中的参数

同C语言,但支持更多特性

实参传递

值、指针

值、指针、引用

默认参数

不支持

支持

引用参数

不支持

支持

函数重载

不支持

支持

参数传递方式对比
1、值传递(两者相同)

代码语言:javascript

AI代码解释

// C
void func(int a) { a = 10; }

// C++
void func(int a) { a = 10; }
2、指针传递(两者相同)

代码语言:javascript

AI代码解释

// C
void func(int *a) { *a = 10; }

// C++
void func(int *a) { *a = 10; }
3、引用传递(仅C++)

代码语言:javascript

AI代码解释

// 仅C++
void func(int &a) { a = 10; }
默认参数对比
C语言(不支持)

代码语言:javascript

AI代码解释

// 错误!C不支持默认参数
void func(int a = 10); 
C++(支持)

代码语言:javascript

AI代码解释

// C++支持
void func(int a = 10); 

int main() {
    func();  // 等同于func(10)
}
函数重载对比
C语言(不支持)

代码语言:javascript

AI代码解释

// 错误!C不支持函数重载
void print(int a);
void print(double a);  // 冲突
C++(支持)

代码语言:javascript

AI代码解释

// C++支持
void print(int a);
void print(double a);  // 合法重载
可变参数对比
C语言(使用stdarg.h)

代码语言:javascript

AI代码解释

#include <stdarg.h>

void printArgs(int count, ...) {
    va_list args;
    va_start(args, count);
    // ...
    va_end(args);
}
C++(支持C方式,也提供模板方式)

代码语言:javascript

AI代码解释

// 方式1:兼容C
#include <cstdarg>
void printArgs(int count, ...);

// 方式2:可变参数模板(C++11)
template<typename... Args>
void printArgs(Args... args);
重要区别总结

1、引用传递:C++特有,C语言只能用指针模拟;

2、默认参数:C++特有,C语言不支持;

3、函数重载:C++特有,C语言不支持;

4、const引用:C++可以使用const引用避免拷贝;

代码语言:javascript

AI代码解释

void func(const std::string &s);  // C++高效传递大对象

5、右值引用:C++11新增(C++特有);

代码语言:javascript

AI代码解释

void func(std::string &&s);  // 移动语义
实践建议
  1. C语言
    • 使用指针实现"引用"效果;
    • 大型结构体通过指针传递避免拷贝;
    • 明确文档说明参数用途。
  2. C++
    • 优先使用const引用传递大对象;
    • 简单内置类型可用值传递;
    • 需要修改的参数使用普通引用;
    • 利用函数重载提高接口可用性;
    • C++11后考虑使用移动语义优化大对象传递。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐