01.README.md/pointer_copy

# pointer_copy

简介
- 演示基于指针的整数数组遍历与复制。包含前向复制(copy_forward)和在重叠区域下的安全复制(copy_safe,类似 memmove)。

目的
- 理解指针算术(p + n、p++)与数组名退化为指针的含义。
- 掌握重叠内存拷贝为何需要选择合适的拷贝方向(前向或后向)。

主要文件
- pointer_copy.c — 示例源码(遵循 snake_case、指针后缀 `_ptr`、输出参数 `*_out` 约定)

编译与运行(说明)
- 可使用标准 C 编译器(例如 gcc/clang)进行编译并在本地运行,或在支持的交叉编译环境下交叉编译再在目标平台运行。

示例输出(大致)
- source array before copy: 1 2 3 4 5 6
- destination array after copy_forward: 1 2 3 4 5 6
- buffer before overlap copy: 10 20 30 40 50 60
- buffer after overlap copy (safe): 10 20 10 20 30 40

学习要点
- `arr[i]` 等价于 `*(arr + i)`。
- 指针加法以元素为单位(`p + 1` 增加 `sizeof(*p)` 字节)。
- 当 `destination > source` 且存在重叠时,应从后向前复制以避免覆盖尚未复制的数据。
- one-past-the-end(如 `src + n`)可作为边界比较,但不能解引用。

扩展练习
- 在 `copy_safe` 中打印 `read_ptr`/`write_ptr` 的地址和值以便观察。
- 实现并比较 `memcpy`、`memmove` 与手写实现的差异。
- 实现数组/字符串的 in-place 反转。

注意事项
- 调用方需保证传入的 `element_count` 合理且内存有效;跨对象的指针算术为未定义行为。
/*
 * pointer_copy.c
 *
 * - 命名风格:snake_case
 * - 指针变量以 _ptr 后缀表示(如 read_ptr、write_ptr)
 * - 避免单字符变量名,使用 element_count、index、buffer_size 等语义化名称
 */

#include <stdio.h>
#include <stddef.h> /* for size_t */

void print_int_array(const int *source_array_ptr, size_t element_count, const char *label_text) {
    if (label_text == NULL) label_text = "(null)";
    printf("%s:", label_text);
    for (size_t index = 0; index < element_count; ++index) {
        printf(" %d", source_array_ptr[index]);
    }
    printf("\n");
}

/* 向前复制(当 source 与 destination 不重叠时安全) */
void copy_forward(const int *source_array_ptr, int *destination_array_ptr, size_t element_count) {
    const int *read_ptr = source_array_ptr;
    int *write_ptr = destination_array_ptr;
    const int *source_end_ptr = source_array_ptr + element_count;

    while (read_ptr < source_end_ptr) {
        *write_ptr++ = *read_ptr++;
    }
}

/* 安全复制(简单 memmove 思路):
 * 若目标在源之后且有重叠,则从后向前复制;否则前向复制。
 */
void copy_safe(const int *source_array_ptr, int *destination_array_ptr, size_t element_count) {
    if (element_count == 0) return;

    if (destination_array_ptr > source_array_ptr &&
        destination_array_ptr < source_array_ptr + element_count) {
        /* 后向复制:初始化为 one-past-the-end,然后先 -- 再解引用 */
        const int *read_ptr = source_array_ptr + element_count;
        int *write_ptr = destination_array_ptr + element_count;
        while (element_count--) {
            *--write_ptr = *--read_ptr;
        }
    } else {
        /* 向前复制 */
        const int *read_ptr = source_array_ptr;
        int *write_ptr = destination_array_ptr;
        while (element_count--) {
            *write_ptr++ = *read_ptr++;
        }
    }
}

int main(void) {
    /* 示例 1:不重叠的源数组与目标数组 */
    int source_array[] = {1, 2, 3, 4, 5, 6};
    int destination_array[6] = {0};
    size_t element_count = sizeof(source_array) / sizeof(source_array[0]);

    print_int_array(source_array, element_count, "source array before copy");
    copy_forward(source_array, destination_array, element_count);
    print_int_array(destination_array, element_count, "destination array after copy_forward");

    /* 示例 2:同一数组内重叠复制,需要安全后向复制 */
    int buffer_array[] = {10, 20, 30, 40, 50, 60};
    const size_t buffer_size = sizeof(buffer_array) / sizeof(buffer_array[0]);
    const size_t overlap_count = 4; /* 复制的元素个数 */

    print_int_array(buffer_array, buffer_size, "buffer before overlap copy");
    /* 将 buffer_array[0..3] 复制到 buffer_array[2..5] */
    copy_safe(buffer_array, buffer_array + 2, overlap_count);
    print_int_array(buffer_array, buffer_size, "buffer after overlap copy (safe)");

    return 0;
}

02.README.md/multi_return

# multi_return

简介
- 演示如何通过指针参数返回多个值(输出参数),以及如何在堆上分配内存并将指针返回给调用者(调用者负责 free)。

目的
- 理解 C 函数参数按值传递的语义,以及如何通过传入地址修改调用者的数据。
- 理解 malloc/free 的用法与异常处理(检查 NULL),以及不要返回局部栈地址的原因。

主要文件
- multi_return.c — 示例源码(使用 `*_out` 作为输出参数后缀,堆上分配返回指针以 `_ptr` 结尾)

编译与运行(说明)
- 使用常见的 C 编译器进行编译;在运行前请确保所用环境允许分配堆内存,并注意检查 malloc 返回值。

示例输出(大致)
- value_a=6 value_b=7 sum=13 product=42
- squares: 0 1 4 9 16

学习要点
- 使用 `&sum_out`、`&product_out` 把结果写回调用者内存。
- `malloc` 可能返回 `NULL`,必须检测并妥善处理。
- 不要返回指向局部变量或局部数组的指针(会出现悬垂指针)。
- 若需返回多个值,可考虑返回 `struct` 以减少输出参数。

扩展练习
- 将 `sum_and_product` 改为返回 `struct`,比较两种接口优劣。
- 在 `make_squares` 中加入越界与溢出检查,以及对极大 `n` 的防护策略。
- 模拟内存分配失败并验证程序行为。

注意事项
- 使用 `free` 释放 `malloc` 分配的内存以避免内存泄漏。
- 输出参数可为 `NULL`,函数应能安全处理(示例已实现)。
/*
 * multi_return.c
 *
 * - 命名风格:snake_case
 * - 输出参数使用 *_out 风格(如 sum_out、product_out)
 * - 动态分配返回指针命名使用 _ptr 后缀(如 square_array_ptr)
 */

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h> /* for size_t */

/* 通过输出参数返回和与积(输出参数可为 NULL 表示调用者不需要该输出) */
void sum_and_product(int value_a, int value_b, int *sum_out, int *product_out) {
    if (sum_out) *sum_out = value_a + value_b;
    if (product_out) *product_out = value_a * value_b;
}

/* 在堆上分配 element_count 个 int,返回指针(调用者负责 free) */
int *make_squares(size_t element_count) {
    int *square_array_ptr = malloc(element_count * sizeof(int));
    if (!square_array_ptr) return NULL;
    for (size_t index = 0; index < element_count; ++index) {
        square_array_ptr[index] = (int)(index * index);
    }
    return square_array_ptr;
}

int main(void) {
    int value_a = 6;
    int value_b = 7;
    int sum_out_value = 0;
    int product_out_value = 0;

    sum_and_product(value_a, value_b, &sum_out_value, &product_out_value);
    printf("value_a=%d value_b=%d sum=%d product=%d\n",
           value_a, value_b, sum_out_value, product_out_value);

    const size_t element_count = 5;
    int *square_array_ptr = make_squares(element_count);
    if (!square_array_ptr) {
        fprintf(stderr, "make_squares failed\n");
        return 1;
    }

    printf("squares:");
    for (size_t index = 0; index < element_count; ++index) {
        printf(" %d", square_array_ptr[index]);
    }
    printf("\n");

    free(square_array_ptr);
    return 0;
}

03-README.md/string_pointer

# string_pointer

简介
- 演示指针与 C 字符串的基本操作:基于指针实现的 `my_strlen`、`my_strcpy`,以及指针数组(类似 `argv`)的使用。

目的
- 掌握 C 字符串以 `'\0'` 终止的语义以及 `const` 在字符串上下文中的作用。
- 理解指针数组与 `char **` 的关系,学习如何遍历字符串与字符串数组。

主要文件
- string_pointer.c — 示例源码(`my_strlen`、`my_strcpy`、指针数组示例)

编译与运行(说明)
- 使用常见 C 编译器编译并运行;请在运行时保证目标缓冲区有足够大小以避免溢出。

示例输出(大致)
- string: "hello, pointer!"
- my_strlen = 16
- copied string: "hello, pointer!"
- iterate words using char **:
  - one (length 3)
  - two (length 3)
  - three (length 5)

学习要点
- `my_strlen` 用指针遍历直到遇到 `'\0'`,返回 `p - s`。
- `my_strcpy` 可用 `(*d++ = *s++)` 的赋值方式一次复制一个字符,包括终止符。
- 字符串字面量通常位于只读静态区,应通过 `const char *` 引用并避免写入。
- 指针数组的元素是指向字符串的指针(`const char * words[]`),数组在表达式中可退化为 `const char **`。

扩展练习
- 实现 `my_strchr`、`my_strncmp`、`my_strcat`。
- 实现带边界检查的安全版 `my_strncpy` 或 `my_strlcpy`。
- 比较指针实现与索引实现的性能差别(micro-benchmark)。

注意事项
- 传入 `NULL` 或非 NUL 结尾的内存会导致未定义行为。
- 写入目标缓冲区前应确保其大小足够以避免缓冲区溢出。
/*
 * string_pointer.c
 *
 * - 命名风格:snake_case
 * - 指针使用 _ptr 后缀(如 scan_ptr、dest_ptr)
 * - 避免单字符变量名(使用 index、buffer_size 等)
 */

#include <stdio.h>
#include <stddef.h> /* for size_t */

/* 基于指针遍历实现 strlen */
size_t my_strlen(const char *text_literal_ptr) {
    const char *scan_ptr = text_literal_ptr;
    while (*scan_ptr) ++scan_ptr;
    return (size_t)(scan_ptr - text_literal_ptr);
}

/* 基于指针实现 strcpy(假设 dest_buffer_ptr 足够大) */
char *my_strcpy(char *dest_buffer_ptr, const char *src_text_ptr) {
    char *dest_ptr = dest_buffer_ptr;
    while ((*dest_ptr++ = *src_text_ptr++))
        ; /* 复制包括末尾 '\\0' */
    return dest_buffer_ptr;
}

int main(void) {
    const char *text_literal = "hello, pointer!";
    printf("string: \"%s\"\n", text_literal);
    printf("my_strlen = %zu\n", my_strlen(text_literal));

    const size_t buffer_size = 64;
    char buffer_destination[64];
    my_strcpy(buffer_destination, text_literal);
    printf("copied string: \"%s\"\n", buffer_destination);

    /* 指针数组示例(类似 argv) */
    const char *word_list[] = {"one", "two", "three", NULL};
    const char **current_word_ptr = word_list;

    printf("iterate words using char **:\n");
    while (*current_word_ptr) {
        const char *current_word_ptr_value = *current_word_ptr;
        printf("  %s (length %zu)\n", current_word_ptr_value, my_strlen(current_word_ptr_value));
        ++current_word_ptr;
    }

    return 0;
}
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐