代碼現場
int main() {
int n, m;
cin >> n >> m;
bool str[n+1]; // ❌ VLA:變長數組,C++標準不支持
// ...
}
編譯器行為差異
| 編譯器 | 標準模式 | 行為 | 原因 |
| VC++ 6.0 | 預C++98 | 報錯 | 不支持VLA,嚴格遵循標準 |
| Dev-C++ (GCC) | GNU擴展 | 編譯通過 | GCC默認啟用 `-std=gnu++98` 支持VLA擴展 |
| MSVC (VS2019+) | /std:c++17 | 報錯 C2133 | 標準禁止VLA |
| GCC/Clang | -std=c++17 | 報錯 | 標準模式禁用GNU擴展 |
| GCC/Clang | -std=gnu++17 | 通過(警告) | GNU擴展模式允許VLA |
三種標準合規替代方案
// 方案1:std::vector(推薦,自動管理內存)
std::vector str(n + 1, false);
// 方案2:new[] / delete[](手動管理,教學用)
bool *str = new bool[n + 1]();
delete[] str; // 必須釋放
// 方案3:std::unique_ptr(現代C++,RAII)
auto str = std::make_unique(n + 1);
全局/靜態數組 vs 局部數組
| 特性 | 全局/靜態數組 | 局部數組(棧) | 動態數組(堆) |
| 生命周期 | 程序全周期 | 函數調用期間 | 手動控制 |
| 大小確定 | 編譯期常量 | 編譯期常量 / VLA(非標) | 運行期變量 |
| 內存區域 | .data/.bss段 | 棧(默認1-8MB) | 堆(GB級) |
| 跨函數訪問 | 需extern聲明 | 不可直接訪問 | 傳遞指針/引用 |
約瑟夫問題優化版
#include
#include
#include
using namespace std;
int main() {
int n, m;
if (!(cin >> n >> m)) return 0;
vector eliminated(n + 1, false); // 標準合規
int remaining = n;
int pos = 0, count = 0;
while (remaining > 0) {
pos = (pos % n) + 1; // 環狀遍歷 1..n
if (!eliminated[pos]) {
if (++count == m) {
eliminated[pos] = true;
cout << pos << setw(5);
if (--remaining) cout << endl;
count = 0;
}
}
}
return 0;
}
總結
VLA是GCC擴展,**標準C++禁止**。VC6報錯是正確的,Dev-C++通過是寬容的。現代C++請無腦使用`std::vector`,安全、標準、無內存洩漏。