项目

一般

简介

行为

支持 #466

打开

fortran 多维数组与 c++ 的区别

李立奎3 天 之前添加. 更新于 3 天 之前.

状态:
新建
优先级:
普通
指派给:
-
开始日期:
2026-01-15
计划完成日期:
% 完成:

0%

预期时间:
#2:

描述

从 C++ 背景来看,Fortran 多维数组有几个关键区别需要特别注意,尤其是内存布局的差异会直接影响代码逻辑和性能。

1. 内存布局:列主序 vs 行主序

这是最本质的区别:

  • C++:行主序(Row-major)

    int arr[3][4]; // 内存中:arr[0][0], arr[0][1], ..., arr[0][3], arr[1][0], ...
    // 遍历性能:for(i) for(j) 访问 arr[i][j] 是连续的
    
  • Fortran:列主序(Column-major)

    integer :: arr(3,4)  ! 内存中:arr(1,1), arr(2,1), arr(3,1), arr(1,2), ...
    ! 遍历性能:do j = 1,4; do i = 1,3; 访问 arr(i,j) 是连续的
    

影响:嵌套循环顺序需要反转,否则性能会大幅下降。

2. 下标起始:默认 1-based

integer :: a(10)      ! 索引 1..10
integer :: b(0:9)     ! 可以显式指定 0..9
integer :: c(-5:5)    ! 甚至可以是负数范围

3. 数组声明语法

! Fortran(维度在后)
real :: matrix(10, 20)          ! 10行20列
real, allocatable :: dyn(:,:)   ! 可分配数组

! C++(维度在前)
double matrix[10][20];
std::vector<std::vector<double>> dyn;

4. 数组整体操作

Fortran 支持直接的数组运算,无需循环:

real :: a(100), b(100), c(100)
a = b + c              ! 逐元素相加
a = sqrt(b)            ! 逐元素开方
where (b > 0) a = log(b)

C++ 需要 std::transform 或手写循环。

5. 数组切片

! 提取子数组
real :: big(100, 100), small(10, 10)
small = big(1:10, 21:30)  ! 直接切片复制

6. 函数传参:形状信息可保留

subroutine process(arr)
  real, intent(inout) :: arr(:,:)  ! 假设形状,接收任意大小
  ! 可通过 size(arr,1) 获取各维度
end subroutine

! 调用
call process(my_array)  ! 无需额外传递维度信息

C++ 中通常需要模板或额外参数传递维度。

7. 动态数组

real, allocatable :: arr(:,:)
allocate(arr(n, m))
...
deallocate(arr)

! 自动重新分配
arr = reshape(source_array, [new_n, new_m])

总结对比表

特性 Fortran C++
内存顺序 列主序 行主序
默认索引 1-based 0-based
数组运算 原生支持 需库/手动实现
切片 语法级支持 需指针/引用操作
传参 可保留形状信息 通常退化或需模板
性能敏感 按列遍历 按行遍历

建议:从 C++ 转向 Fortran 时,最需要注意的就是反转循环顺序以匹配列主序,否则缓存命中率会很差。

行为 #1

李立奎 更新于 3 天 之前

如果是 Fortran 77,限制会更多,对 C++ 程序员来说会更不友好:

1. 无动态数组

! F77:必须是固定大小或显式传参
subroutine process(arr, n, m)
  integer n, m
  real arr(n, m)  ! 需要显式传递维度作为参数
end subroutine

! 无法像 F90+ 那样用 allocatable 或 assumed shape

2. 循环必须写全

      do 10 j = 1, n
        do 10 i = 1, m
          arr(i, j) = ...
10    continue
! 无法像 F90+ 用 forall 或数组整体运算

3. 无数组语法糖

  • 没有 arr = b + c 这样的整体赋值
  • 没有 arr(1:10) 这样的切片语法
  • 所有操作必须手写循环

4. 字符串是字符数组

character*80 str  ! 固定长度,不像 C++ 的 std::string

5. 无接口检查

  • 函数调用不检查数组边界和类型
  • 容易传错维度导致内存越界

6. 列主序依然成立

虽然语法受限,但列主序规则不变,遍历顺序仍需注意:

! 正确(连续访问内存)
do j = 1, n
  do i = 1, m
    arr(i, j) = ...

总结:F77 的数组系统更像 C 的原始数组,没有现代 Fortran 的高级特性,但内存布局和性能考量点仍然相同。

行为

导出 Atom PDF