C/C++

C/C++

Dynamic Array and Static Array

在C和Java中,判断一个数组是动态数组还是静态数组的方式有所不同,因为两者的内存管理机制和语法规则不同。以下是具体的判断方法:


C语言

在C语言中,数组的存储方式决定了它是静态数组还是动态数组。

1. 静态数组

  • 静态数组的大小在编译时确定,并且分配在栈(stack)或全局/静态存储区。

  • 判断方法:

    • 如果数组的大小是固定的(例如 int arr[10];),并且没有使用动态内存分配函数(如 malloccalloc 等),那么它是静态数组。
    • 如果数组是全局变量或静态局部变量(例如 static int arr[10];),它也是静态数组。

    示例:

    int arr[10]; // 静态数组,大小在编译时确定
    static int arr2[20]; // 静态数组,存储在静态存储区

2. 动态数组

  • 动态数组的大小在运行时确定,并且分配在堆(heap)上。

  • 判断方法:

    • 如果数组是通过动态内存分配函数(如 malloccallocrealloc)创建的,那么它是动态数组。
    • 动态数组的大小可以在运行时动态调整。

    示例:

    int n = 10;
    int* arr = (int*)malloc(n * sizeof(int)); // 动态数组,分配在堆上

Java语言

在Java中,数组都是动态分配的(因为Java没有栈分配的数组),但可以通过声明方式和使用方式来区分“静态”和“动态”行为。

1. 静态数组

  • 静态数组的大小在声明时确定,并且分配在堆上。

  • 判断方法:

    • 如果数组的大小在声明时固定(例如 int[] arr = new int[10];),并且没有后续调整大小,那么它类似于静态数组。
    • 如果数组是类的静态成员变量(例如 static int[] arr = new int[10];),它也是静态数组。

    示例:

    int[] arr = new int[10]; // 类似于静态数组,大小固定
    static int[] arr2 = new int[20]; // 静态数组,作为类的静态成员

2. 动态数组

  • 动态数组的大小可以在运行时动态调整。

  • 判断方法:

    • 如果数组的大小在运行时动态确定(例如通过用户输入或计算),或者使用集合类(如 ArrayList)动态调整大小,那么它是动态数组。

    示例:

    int n = 10;
    int[] arr = new int[n]; // 动态数组,大小在运行时确定

    // 使用 ArrayList 实现动态数组
    ArrayList<Integer> list = new ArrayList<>(); // 动态数组,大小可动态调整

总结

特性 C语言 Java语言
静态数组 大小在编译时确定,分配在栈或静态存储区 大小在声明时确定,分配在堆上
动态数组 大小在运行时确定,分配在堆上 大小在运行时确定,或使用集合类动态调整
判断方法 是否使用 malloc 等动态分配函数 是否在运行时确定大小或使用 ArrayList
  • 在C语言中,静态数组和动态数组的区别在于内存分配方式(栈 vs 堆)。
  • 在Java中,所有数组都是动态分配的,但可以通过声明方式和使用方式区分“静态”和“动态”行为。

Clangd

clang-format

To generate a .clang-format file with, for example, LLVM code style, run the following command (make sure to have ClangTools already installed):

clang-format -style=llvm -dump-config > .clang-format

查看C/C++头文件搜索路径及其顺序

你可以通过查看编译器的文档或运行以下命令来确认搜索路径的顺序

echo | gcc -E -x c -v -

这个命令会显示 GCC 的内部信息,包括默认的包含路径和它们的搜索顺序。

使用绝对路径

不推荐,因为这样会降低可移植性。

#include "/usr/local/include/khrplatform.h"

调整编译命令

在编译时指定包含路径的顺序,例如:

g++ -I/usr/local/include -I/usr/include your_file.cpp -o your_program

这样可以明确告诉编译器首先搜索 /usr/local/include。

使用编译器的 -H 选项

运行编译命令时,加上 -H 选项,可以显示实际包含的头文件及其路径:

g++ -H your_file.cpp

多文件编译

如果多个文件中都定义了全局的(非static)expr函数,在链接阶段会发生“multiple definition”错误,因为链接器会发现同名的符号冲突。解决办法包括:

  • 保证同一函数只定义一次,并在其它文件中通过 extern 声明使用;
  • 或者如果函数只在本文件内部使用,可以定义为 static,使其具有内部链接,互不干扰。