"Introduction to C Language" explores C language functions

preface

In modern programming, functions are regarded as the cornerstone of software development, whether it is a small script or a large application, it is inseparable from the support of functions. C language, as a widely used programming language, deeply embodies the importance of functions in building maintainable, efficient and modular code . In this blog, we will explore all aspects of C language functions in depth, from basic concepts to advanced applications, to help you better understand and apply functions.

1. Function overview

Definition and function

A function is a block of code that encapsulates a specific task or operation. It takes input, performs operations, and may return output. Functions make problems more tractable and understandable by dividing code logic into small chunks. This modular approach helps reduce code complexity and improve code quality.

importance

  1. Modularity and maintainability: Functions allow complex tasks to be broken down into smaller, more manageable parts. This modular approach makes it easier to locate and fix problems, improving code maintainability.
  2. Code reuse: Write a function once and call it in many places. This eliminates the need to repeatedly write similar code, saving time and effort.
  3. Readability: Functions divide tasks into logical blocks, making code logic clearer. Reasonable function naming and abstraction level can make the code easier to understand.
  4. Team collaboration: Functions enable team members to independently develop and maintain different functional modules, improving team efficiency and collaboration capabilities.

2. Function classification

Library Functions

Library functions are predefined functions in the C language that provide implementations of many common tasks. It's like a programmer's toolbox that you can use whenever you want without having to write code from scratch.

  • I/O function ( stdio.h):

    • printf: Used to output formatted information on the screen.
    • scanf: Used to read input from the keyboard and parse the input according to the format string.
    #include <stdio.h>
    
    int main() {
          
          
        printf("Hello, World!\n");
        int num;
        scanf("%d", &num);
        return 0;
    }
    
  • Mathematical function ( math.h):

    • sqrt: Calculates the square root of a given number.
    • pow: Calculates the exponent power of a number.
    #include <math.h>
    
    int main() {
          
          
        double squareRoot = sqrt(25.0);
        double power = pow(2.0, 3.0);
        return 0;
    }
    
  • String function ( string.h):

    • strlen: Calculate the length of the string.
    • strcpy: Copy a string to another string.
    #include <string.h>
    
    int main() {
          
          
        char str1[] = "Hello";
        char str2[10];
        strcpy(str2, str1);
        return 0;
    }
    

By using these library functions, you can easily perform various tasks without having to write code from scratch. Library functions have been optimized and tested so they improve code stability and efficiency.

custom function

A custom function is a block of code that you write yourself to accomplish a specific task. By dividing your code into custom functions, you can make your program more modular and maintainable. Let's see in more detail how to define, call and use custom functions.

definition

A custom function is written by the programmer as needed, and usually includes the following components:

  • Return Type (Return Type): Indicates the data type returned by the function, which can be integer, floating point number, character, etc.
  • Function Name (Function Name): The identifier of the function, which is used to uniquely identify the function in the program.
  • Parameter List (Parameter List): A set of comma-separated parameters used to pass data to the function.
  • Function Body: Contains the actual code that performs a specific task.
// 自定义函数的定义
返回类型 函数名(参数列表) {
    
    
    // 函数体
    // 执行任务的代码
}

use

Let's walk through an example to demonstrate how to define and use custom functions. We are going to write a function that calculates the sum of two integers.

#include <stdio.h>

// 自定义函数,计算两个整数的和
int add(int a, int b) {
    
    
    return a + b;
}

int main() {
    
    
    int num1 = 5, num2 = 3
    int result = add(num1, num2);  // 调用自定义函数
    printf("Sum: %d\n", result);
    return 0;
}

In this example, we first define a addcustom function called . It takes two integer arguments aand breturns the result after adding them in the function body. In mainthe function, we call this custom function and pass it num1the and num2as parameters. Finally, we output the result.

benefit

  • Modularity: Split complex tasks into small pieces that are easy to manage and understand.
  • Reusability: Write a function once and call it in multiple places to avoid duplication of code.
  • Readability: Function names and function descriptions are clear, improving code readability.
  • Maintainability: The modification function only needs to be performed in one place without affecting other codes.

3. Function parameters

actual parameters (actual parameters)

Actual parameters, also known as arguments, are values ​​or variables that are passed to a function when it is called. They are the actual data in the function call, used by the function at execution time. Actual parameters can be constants, variables, expressions, etc.

Let's understand the concept of actual parameters with an example:

#include <stdio.h>

// 自定义函数,计算两个数的平均值
double average(double num1, double num2) {
    
    
    return (num1 + num2) / 2;
}

int main() {
    
    
    double a = 10.0, b = 20.0;
    double result = average(a, b);  // 传递实际参数 a 和 b
    printf("Average: %lf\n", result);
    return 0;
}

In this example, aand bare the actual parameters that are passed to averagethe function, which is used to calculate the average.

Formal parameters (parameters)

Formal parameters, also known as formal parameters, are parameters declared when a function is defined. They are part of the function definition and are used to receive the actual parameters passed when calling the function. Formal parameters are used as variables inside the function body.

Let us understand the concept of formal parameters with an example:

#include <stdio.h>

// 自定义函数,计算两个数的平均值
double average(double num1, double num2) {
    
      // 形式参数 num1 和 num2
    return (num1 + num2) / 2;
}

int main() {
    
    
    double a = 10.0, b = 20.0;
    double result = average(a, b);  // 传递实际参数 a 和 b
    printf("Average: %lf\n", result);
    return 0;
}

In this example, num1and num2are formal parameters, declared in the function definition. When the function is called, the actual parameters aand bwill be passed to the formal parameters.

Function parameters are an important way to pass data in a function call. The actual parameter is the actual value passed when the function is called , while the formal parameter is the variable declared in the function definition to receive the value of the actual parameter. By understanding what the parameters do, you can gain more control over the behavior and capabilities of the function.

memory allocation

Memory allocation for actual parameters (actual parameters):

The actual parameters are passed to the function when the function is called, usually by value. This means that the function receives a copy of the value of the argument, not the argument itself. Doing so ensures that the original value of the actual parameter is not affected by the function call.

Memory allocation for formal parameters (formal parameters):

Formal parameters are declared in the function definition and are used to receive the values ​​of the actual parameters. They are usually local variables that are automatically allocated when the function is called. The memory for the formal parameters is allocated when the function is called and freed when the function finishes executing.

Precautions:

  1. Passing by value and passing by pointer: In C language, parameter passing can be realized by passing by value or passing by pointer. Passing by value copies the value of the actual parameter, while passing by pointer passes the memory address of the actual parameter. When passed by pointer, the function can modify the value of the actual parameter.
  2. Memory overhead: When the function is called, the copy of each actual parameter requires a certain amount of memory overhead. If the actual parameters are large, multiple function calls may lead to excessive memory usage. At this time, pointer passing can be used to reduce memory overhead.
  3. Memory management: If memory is dynamically allocated inside the function (such as using malloca function), make sure to release the memory after the function ends to avoid memory leaks.
  4. Scope: The scope of formal parameters is limited to the inside of the function. They cannot be accessed outside the function. The scope of the actual parameter is in the context of the function call.
  5. Return value passing: The return value of the function is also passed to the caller by value passing. If a complex type (such as a structure) is returned, the system will automatically handle its copying.

Understanding how actual and formal parameters are handled in memory, and the difference between passing by value and passing by pointer, is very important for using function parameters correctly. Managing memory properly, avoiding memory leaks, and understanding how data is passed between function calls will help you write more robust and efficient programs.

4. Function call

When we call a function in a program, the way parameters are passed affects how the function handles the data. Let's explore in more detail how functions are called, and how they operate in memory, with examples.

call by value

Call by value is a method of parameter passing, which means that when the function is called, the function will get a copy of the actual parameter . This way, operations inside the function do not affect the value of the original actual parameter . Let's look at an example that swaps two integer values:

#include <stdio.h>

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

int main() {
    
    
    int x = 5, y = 10;
    printf("Original values: x = %d, y = %d\n", x, y);

    swapByValue(x, y);
    printf("After swapByValue: x = %d, y = %d\n", x, y);

    return 0;
}

In this example, swapByValuealthough the function swaps aand , the values ​​of and outside the function do not change, because the function gets a copy of and .bxyxy

call by address

Call by reference uses pointers to pass parameters, which means that the function gets the memory address of the actual parameter . By manipulating these memory addresses, the function can directly change the value of the actual parameter . Let's use the swap function again to demonstrate call by reference:

#include <stdio.h>

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

int main() {
    
    
    int x = 5, y = 10;
    printf("Original values: x = %d, y = %d\n", x, y);

    swapByReference(&x, &y);
    printf("After swapByReference: x = %d, y = %d\n", x, y);

    return 0;
}

In this example, we pass the addresses of xand yto swapByReferencethe function. By manipulating these addresses, the function successfully realizes the exchange of xand y.

5. Function nested call and chain access

nested calls

Function nesting refers to calling another function inside a function. In this way, you can break a large task into smaller subtasks and assign them to different functions to complete. Nesting calls can make code more modular and readable.

Let's understand nested calls with an example:

#include <stdio.h>

// 函数A:打印数字
void printNumber(int num) {
    
    
    printf("Number: %d\n", num);
}

// 函数B:调用函数A两次
void callPrintNumberTwice(int num1, int num2) {
    
    
    printNumber(num1);
    printNumber(num2);
}

int main() {
    
    
    int x = 5, y = 10;

    callPrintNumberTwice(x, y); // 嵌套调用

    return 0;
}

In this example, callPrintNumberTwicethe function calls the function twice internally printNumberto print two numbers.

chain access

Chaining refers to calling multiple functions consecutively in one expression. This approach can make the code more compact and easy to understand, especially for a series of related operations.

Let's understand chained access with an example:

#include <stdio.h>

// 函数A:返回数字的平方
int square(int num) {
    
    
    return num * num;
}

// 函数B:返回数字的两倍
int doubleNumber(int num) {
    
    
    return num * 2;
}

int main() {
    
    
    int x = 5;

    int result = doubleNumber(square(x)); // 链式访问
    printf("Result: %d\n", result);

    return 0;
}

doubleNumberIn this example, we have called the function and function in one line square, which implements the operations of squaring and doubling numbers.

Nested calls and chained access of functions are effective means to improve code modularity and readability. Nested calls can break down large tasks into smaller ones, making the code more structured. Chained access can complete multiple operations in one line of code, making the code more compact. By understanding these concepts, you can better design and organize your programs.

6. Function declaration and definition

function declaration

The function declaration is to tell the compiler the existence of the function and how to use it before using the function. They include the function's name, return type, and parameter list. By declaring, the compiler knows how to call the function correctly.

Let's look at an example:

// 函数声明
int add(int a, int b);

int main() {
    
    
    int x = 5, y = 10;
    int result = add(x, y); // 使用函数之前进行了声明
    return 0;
}

// 函数定义
int add(int a, int b) {
    
    
    return a + b;
}

In this example, we maindeclared addthe function before the function. This allows us mainto call it in the function, because the compiler knows that addthe function takes two integer parameters and returns an integer.

function definition

The function definition is to provide the actual code implementation of the function , which tells the compiler what the function should do. A definition includes the function's name, return type, parameter list, and function body (code block).

Look at the example again:

// 函数声明
int add(int a, int b);

int main() {
    
    
    int x = 5, y = 10;
    int result = add(x, y); // 使用函数
    return 0;
}

// 函数定义
int add(int a, int b) {
    
    
    return a + b; // 函数的具体代码实现
}

In this example, addthe definition of the function includes the code in the body of the function, which is the actual addition operation.

The declaration of a function tells the compiler the signature of the function so that the compiler knows the function's existence and parameters before calling the function. The definition of a function provides the concrete code implementation of the function. With these two, we can better organize and use functions. Proper declarations and definitions are very important for writing maintainable and understandable code.

Seven, recursion

concept

Recursion is a programming technique that refers to a function calling itself within itself. In other words, recursion is a method of solving a problem by repeatedly breaking it down into smaller, similar subproblems. This approach is especially useful in situations that can be broken down into problems of the same type.

main idea

The core idea of ​​recursion is to decompose a large problem into one or more small problems, and then solve these small problems through recursive calls. Each recursive call reduces the size of the problem until the problem becomes small enough to be solved by simple means, often called **the "base case"**.

To meet the conditions

The implementation of recursion needs to meet two main conditions:

  1. Base case: Every recursive function must have one or more base cases, that is, cases where the result is not called recursively but returned directly. These base cases are the termination conditions for the recursion, preventing the function from infinitely recursing.
  2. Recursive case: Except for the base case, a recursive function calls itself when solving a problem, but the problem size is reduced so that the base case is eventually reached.

example

Example: Computing factorial

The factorial is the product of all positive integers less than or equal to a positive integer.

  1. Base case: The base case is the termination condition of the recursion. In this example, the base case is when the factorial is computed on 0 or 1, and the result of the factorial is 1. This is because the factorial of 0 and the factorial of 1 are both 1.
  2. Recursive case: Recursive case refers to how we decompose a problem into smaller sub-problems. When computing the factorial, we decompose the problem into the computation (n - 1)!, where nis the current number. This is because is n!equal to nmultiplied by (n - 1)!. (n - 1)!We solve this subproblem by calling recursively .

Let's represent this in code:

#include <stdio.h>

// 递归函数计算阶乘
int factorial(int n) {
    
    
    if (n == 0 || n == 1) {
    
    
        return 1; // 基本情况
    } else {
    
    
        return n * factorial(n - 1); // 递归情况
    }
}

int main() {
    
    
    int num = 5;
    int result = factorial(num);
    printf("Factorial of %d is %d\n", num, result);

    return 0;
}

In this example, when we compute 5!, the recursion evaluates 4!, 3!, 2!, 1!, in turn until the base case is reached. Then, all these partial results are combined to get 5!the final result.

By satisfying the base case and the recursive case, we are able to solve the problem recursively, breaking the problem into smaller and smaller subproblems until the base case can return the result directly.

Summarize

In this blog, we have explored various aspects of functions in C language, from basic concepts to advanced applications, to help you better understand and use functional programming.

  1. The basic concept of a function: We start with what a function is, which is a self-contained block of code that takes input and produces output. Functions help us modularize our code, improving maintainability and reusability.
  2. Classification of functions in C language:
    • Library functions: library functions are pre-defined functions, which #includecan be used by importing library files. We discussed the use and purpose of library functions in detail.
    • Custom Function: A custom function is written by a programmer to solve a specific problem. We explored how to define and call custom functions, and showed examples of their usage.
  3. Function parameters: We discussed actual and formal parameters, and memory considerations during function calls. Function parameters are the bridge to transfer data and information, and the correct use of parameters is crucial to the correct operation of the function.
  4. Calling functions: We covered call-by-value and call-by-reference in detail, illustrating their differences with examples. Understanding these calling methods helps us better control the data passing and interaction between functions.
  5. Nested calls and chained access of functions: Nested calls and chained accesses are advanced techniques of function calls. We illustrate their concepts and explain with examples how to apply them in a program to improve the modularity and compactness of the code.
  6. Function declaration and definition: Function declaration and definition are the key in code organization. We explained the purpose of function declarations and definitions, and how they help us use functions correctly in our programs.
  7. Function Recursion: Recursion is a powerful programming technique to solve problems by calling itself inside a function. We discussed in detail the concept of recursion, the two necessary conditions, and comparison with iteration, and illustrated how recursion works by computing the factorial example.

Through this blog, you should have a deeper understanding of all aspects of functions in C language. Functions are the foundation of programming, mastering the use and principles of functions will help you write clearer, modularized and efficient code.

Guess you like

Origin blog.csdn.net/2301_79480904/article/details/132463900