C語言中形參和實參的區(qū)別小結(jié)
本文介紹了C語言中形參和實參的核心概念。形參是函數(shù)定義中的參數(shù),在調(diào)用時分配內(nèi)存并接收實參的值;實參則是函數(shù)調(diào)用時傳入的具體值或表達式。C語言默認采用傳值調(diào)用機制,通過指針可實現(xiàn)傳址調(diào)用。文章還詳細講解了數(shù)組、結(jié)構(gòu)體、函數(shù)指針等不同類型的參數(shù)使用方法,以及const參數(shù)保護、可變參數(shù)等高級特性,并通過示例代碼展示了各種參數(shù)傳遞方式的實際效果。
C語言中的形參和實參
一、核心定義
形參 (Formal Parameter)
- 定義:函數(shù)聲明或定義時括號內(nèi)的參數(shù)
- 內(nèi)存分配:函數(shù)調(diào)用時在棧上分配內(nèi)存
- 特點:是局部變量,只在函數(shù)內(nèi)部有效
- 初始化:被實參初始化
實參 (Actual Argument)
- 定義:函數(shù)調(diào)用時傳入的具體值或表達式
- 特點:必須有確定的值
- 位置:函數(shù)調(diào)用時出現(xiàn)在括號內(nèi)
二、基礎(chǔ)示例
#include <stdio.h>
// 函數(shù)定義 - a, b 是形參
int add(int a, int b) {
return a + b;
}
int main() {
int x = 5, y = 3;
// 函數(shù)調(diào)用 - x, y 是實參
int result = add(x, y);
printf("結(jié)果: %d\n", result); // 輸出: 8
// 直接使用常量或表達式作為實參
result = add(10, 20); // 常量實參
printf("結(jié)果: %d\n", result); // 輸出: 30
result = add(x, y * 2); // 表達式作為實參
printf("結(jié)果: %d\n", result); // 輸出: 11
return 0;
}
三、C語言的參數(shù)傳遞機制
1.傳值調(diào)用 (Call by Value)- C語言的默認方式
#include <stdio.h>
void swap_by_value(int a, int b) {
int temp = a;
a = b;
b = temp;
printf("函數(shù)內(nèi): a=%d, b=%d\n", a, b);
}
int main() {
int x = 10, y = 20;
printf("交換前: x=%d, y=%d\n", x, y);
swap_by_value(x, y); // 只傳遞值的副本
printf("交換后: x=%d, y=%d\n", x, y); // 原值未改變!
return 0;
}
輸出:
交換前: x=10, y=20
函數(shù)內(nèi): a=20, b=10
交換后: x=10, y=20 // 原值未變!
2.傳址調(diào)用 (Call by Address)- 使用指針
#include <stdio.h>
void swap_by_address(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 10, y = 20;
printf("交換前: x=%d, y=%d\n", x, y);
swap_by_address(&x, &y); // 傳遞地址
printf("交換后: x=%d, y=%d\n", x, y); // 原值改變了!
return 0;
}
3.數(shù)組作為參數(shù)- 實際傳遞的是指針
#include <stdio.h>
// 數(shù)組作為參數(shù)(實際是指針)
void print_array(int arr[], int size) { // int arr[] 等價于 int *arr
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
void modify_array(int arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] *= 2; // 會修改原數(shù)組
}
}
int main() {
int nums[] = {1, 2, 3, 4, 5};
int size = sizeof(nums) / sizeof(nums[0]);
printf("原數(shù)組: ");
print_array(nums, size);
modify_array(nums, size);
printf("修改后: ");
print_array(nums, size); // 數(shù)組內(nèi)容已改變
return 0;
}
四、不同類型的參數(shù)
1. 基本數(shù)據(jù)類型參數(shù)
#include <stdio.h>
// 各種基本類型參數(shù)
void process_basic_types(int i, float f, double d, char c) {
printf("整型: %d\n", i);
printf("浮點: %.2f\n", f);
printf("雙精度: %.4lf\n", d);
printf("字符: %c\n", c);
}
2. 指針參數(shù)
#include <stdio.h>
#include <string.h>
// 字符串處理(使用字符指針)
void string_operations(char *str) {
printf("字符串: %s\n", str);
printf("長度: %zu\n", strlen(str));
// 修改字符串內(nèi)容
str[0] = toupper(str[0]);
}
// 多級指針
void allocate_memory(int **ptr, int size) {
*ptr = (int *)malloc(size * sizeof(int));
if (*ptr != NULL) {
for (int i = 0; i < size; i++) {
(*ptr)[i] = i * 10;
}
}
}
3. 結(jié)構(gòu)體參數(shù)
#include <stdio.h>
// 結(jié)構(gòu)體定義
typedef struct {
int x;
int y;
} Point;
// 傳值 - 傳遞整個結(jié)構(gòu)體的副本
void print_point_by_value(Point p) {
printf("點坐標(biāo): (%d, %d)\n", p.x, p.y);
p.x = 100; // 只修改副本
}
// 傳址 - 傳遞結(jié)構(gòu)體指針
void modify_point_by_address(Point *p) {
p->x += 10;
p->y += 10;
}
// 返回結(jié)構(gòu)體
Point create_point(int x, int y) {
Point p = {x, y};
return p;
}
4. 函數(shù)指針參數(shù)
#include <stdio.h>
// 回調(diào)函數(shù)類型定義
typedef int (*CompareFunc)(int, int);
int max(int a, int b) {
return (a > b) ? a : b;
}
int min(int a, int b) {
return (a < b) ? a : b;
}
// 使用函數(shù)指針作為參數(shù)
int compare_and_process(int a, int b, CompareFunc func) {
return func(a, b);
}
int main() {
int result;
result = compare_and_process(10, 20, max);
printf("較大值: %d\n", result); // 20
result = compare_and_process(10, 20, min);
printf("較小值: %d\n", result); // 10
return 0;
}
五、參數(shù)的高級特性
1. const參數(shù)(保護數(shù)據(jù)不被修改)
#include <stdio.h>
// const保護指針指向的數(shù)據(jù)
void print_string(const char *str) {
// str[0] = 'A'; // 錯誤!不能修改const數(shù)據(jù)
while (*str) {
putchar(*str++);
}
}
// const保護指針本身
void process_array(int *const arr, int size) {
// arr = NULL; // 錯誤!不能修改指針本身
for (int i = 0; i < size; i++) {
arr[i] += 1; // 可以修改指向的數(shù)據(jù)
}
}
2. 可變參數(shù)(stdarg.h)
#include <stdio.h>
#include <stdarg.h>
// 可變參數(shù)函數(shù)
int sum_variable_args(int count, ...) {
int total = 0;
va_list args; // 參數(shù)列表
va_start(args, count); // 初始化
for (int i = 0; i < count; i++) {
total += va_arg(args, int); // 獲取下一個int參數(shù)
}
va_end(args); // 清理
return total;
}
int main() {
printf("總和: %d\n", sum_variable_args(3, 10, 20, 30)); // 60
printf("總和: %d\n", sum_variable_args(5, 1, 2, 3, 4, 5)); // 15
return 0;
}
3. 參數(shù)默認值(C語言不支持,但可用宏模擬)
// 使用宏模擬默認參數(shù)
#define PRINT_MESSAGE(msg, count) print_message_impl(msg, count)
void print_message_impl(const char *msg, int count) {
for (int i = 0; i < count; i++) {
printf("%s\n", msg);
}
}
// 使用重載宏
#define PRINT_MESSAGE_1(msg) PRINT_MESSAGE(msg, 1)
#define PRINT_MESSAGE_2(msg, count) PRINT_MESSAGE(msg, count)
六、重要注意事項
1. 數(shù)組參數(shù)的大小信息丟失
void process(int arr[]) { // 等價于 int *arr
// sizeof(arr) 返回的是指針大小,不是數(shù)組大?。?
// 必須額外傳遞數(shù)組大小參數(shù)
}
2. 參數(shù)的求值順序
int i = 0;
printf("%d, %d, %d\n", i, ++i, i++); // 未定義行為!不同編譯器結(jié)果不同
3. 寄存器變量參數(shù)(register關(guān)鍵字)
// 建議編譯器將參數(shù)放入寄存器(C17起已廢棄,但可了解)
void fast_function(register int x, register int y) {
// 這些參數(shù)可能存儲在寄存器中,訪問更快
}
七、完整示例程序
#include <stdio.h>
#include <stdlib.h>
// 結(jié)構(gòu)體定義
typedef struct {
char name[50];
int age;
float score;
} Student;
// 函數(shù)聲明
void print_student(const Student *s);
void update_score(Student *s, float new_score);
Student create_student(const char *name, int age, float score);
int main() {
// 創(chuàng)建學(xué)生結(jié)構(gòu)體
Student stu = create_student("張三", 20, 85.5);
// 傳址調(diào)用,可以修改原結(jié)構(gòu)體
printf("修改前:\n");
print_student(&stu);
update_score(&stu, 90.0);
printf("\n修改后:\n");
print_student(&stu);
return 0;
}
// 函數(shù)定義
Student create_student(const char *name, int age, float score) {
Student s;
snprintf(s.name, sizeof(s.name), "%s", name);
s.age = age;
s.score = score;
return s; // 返回結(jié)構(gòu)體(C語言支持結(jié)構(gòu)體返回)
}
void print_student(const Student *s) {
printf("姓名: %s\n", s->name);
printf("年齡: %d\n", s->age);
printf("分數(shù): %.1f\n", s->score);
}
void update_score(Student *s, float new_score) {
s->score = new_score; // 直接修改原結(jié)構(gòu)體
}
八、最佳實踐總結(jié)
明確傳遞意圖:
- 不需要修改的參數(shù):使用
const修飾 - 需要修改的參數(shù):使用指針傳遞
- 不需要修改的參數(shù):使用
數(shù)組參數(shù):
- 總是同時傳遞數(shù)組和大小
- 使用
const保護不想被修改的數(shù)組
結(jié)構(gòu)體參數(shù):
- 小結(jié)構(gòu)體:傳值(簡單安全)
- 大結(jié)構(gòu)體:傳址(高效)
- 需要修改的結(jié)構(gòu)體:必須傳址
參數(shù)驗證:
void safe_divide(int numerator, int denominator) { if (denominator == 0) { fprintf(stderr, "錯誤:分母不能為零\n"); return; } // 安全操作... }文檔說明:
/* * 函數(shù):calculate_average * 參數(shù):scores - 分數(shù)數(shù)組(不能為NULL) * count - 數(shù)組元素個數(shù)(必須大于0) * 返回:平均分,如果出錯返回-1 */ float calculate_average(const float *scores, int count);
理解形參和實參是掌握C語言函數(shù)編程的基礎(chǔ),特別是理解C語言嚴格的傳值機制和通過指針實現(xiàn)的傳址效果,這是與許多其他語言的重要區(qū)別。
對于數(shù)組與函數(shù)調(diào)用來說,實參與形參格式不同,實參只需要給出定義名稱即可
到此這篇關(guān)于C語言中形參和實參的區(qū)別小結(jié)的文章就介紹到這了,更多相關(guān)C語言 形參和實參內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望
相關(guān)文章
深入剖析C語言中qsort函數(shù)的實現(xiàn)原理
這篇文章主要介紹了C語言中qsort函數(shù)的實現(xiàn)原理,本文將從回調(diào)函數(shù),qsort函數(shù)的應(yīng)用,qsort函數(shù)的實現(xiàn)原理三個方面進行講解,并通過代碼示例講解的非常詳細,需要的朋友可以參考下2024-03-03
C語言利用system調(diào)用系統(tǒng)命令行詳情
這篇文章主要介紹了C語言利用system調(diào)用系統(tǒng)命令行詳情,system就是調(diào)用系統(tǒng)命令行,輸入為字符串,然后把這個字符串輸出給命令行,讓命令行執(zhí)行。下文的具體內(nèi)容,需要的小伙伴可以參考一下2022-01-01

