You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言代码在在线编译器/CLion表现不稳定,VS运行异常求排查

食品库存变动统计代码的跨编译器异常问题

问题现象

这段统计食品增减变动的代码在在线C编译器上运行完全正常,但在本地IDE中出现异常:

  • CLion:首次运行输出正确,第二次、第三次输出错误值,后续又恢复正常
  • Visual Studio:运行完全异常

已在多台设备和在线编译器验证过代码。

原代码如下:

typedef enum { kus=1,kg } Jednotka;
typedef union { int kus; float kg; } Mnozstvi;
typedef enum { rohlik,chleb,brambory,sirup,merunky,cukr,cokolada,salam,mleko,kava,pivo,mouka,maso,sul,kmin,fazole,meloun } Potravina;
typedef struct { Potravina potr; Jednotka jedn; Mnozstvi mnoz; } Pohyb;

const Pohyb pohyb[]={{chleb,kg,{.kg=20}},{cukr,kg,{.kg=10}},{rohlik,kus,{.kus=70}},{cokolada,kus,{.kus=15}},{kava,kg,{.kg=2}},{mouka,kg,{.kg=5}},
                     {salam,kg,{.kg=6.5}},{mleko,kus,{.kus=30}},{brambory,kg,{.kg=40}},{merunky,kg,{.kg=8}},{sirup,kus,{.kus=18}},{mouka,kg,{.kg=5}},
                     {cukr,kg,{.kg=-1.5}},{cokolada,kus,{.kus=-2}},{brambory,kg,{.kg=-5}},{rohlik,kus,{.kus=-10}},{pivo,kus,{.kus=10}},
                     {kmin,kg,{.kg=.06}},{fazole,kg,{.kg=5}},{chleb,kg,{.kg=-1}},{mleko,kus,{.kus=-2}},{sirup,kus,{.kus=-1}},{pivo,kus,{.kus=25}},
                     {kava,kg,{.kg=6.5}},{mouka,kg,{.kg=-4}},{fazole,kg,{.kg=-.5}},{cukr,kg,{.kg=-2}},{cokolada,kus,{.kus=-3}},{sul,kg,{.kg=6}},
                     {brambory,kg,{.kg=-3.5}},{merunky,kg,{.kg=-.5}},{sirup,kus,{.kus=-3}},{mouka,kg,{.kg=5}},{pivo,kus,{.kus=-1}},
                     {mouka,kg,{.kg=-2}},{maso,kg,{.kg=10}},{maso,kg,{.kg=5.5}},{rohlik,kus,{.kus=-4}},{chleb,kg,{.kg=-3}},{rohlik,kus,{.kus=-35}},
                     {sirup,kus,{.kus=5}},{cokolada,kus,{.kus=-2}},{salam,kg,{.kg=-.3}},{merunky,kg,{.kg=-3}},{maso,kg,{.kg=-.5}},{maso,kg,{.kg=-.8}},
                     {meloun,kg,{.kg=22.5}},{meloun,kg,{.kg=-3.2}},{chleb,kg,{.kg=-.5}},{sirup,kus,{.kus=-1}},{mleko,kus,{.kus=-4}},{sul,kg,{.kg=-1}},
                     {rohlik,kus,{.kus=20}},{maso,kg,{.kg=-1.5}},{pivo,kus,{.kus=-8}}};

const unsigned POHYB=sizeof pohyb/sizeof *pohyb;

const char *nazev[]={"rohlik","chleb","brambory","sirup","merunky","cukr","cokolada","salam","mleko","kava","pivo","mouka","maso","sul","kmin","fazole","meloun"};

#include <stdio.h>

int main() {
    int pocetPotravin = sizeof nazev / sizeof nazev[0]; // 17
    typedef struct {
        Potravina nazev;
        float myMnz;
        Jednotka myJedn;
    } vysPohyb;
    vysPohyb vyspohyb[pocetPotravin];
    for (int i = 0; i < pocetPotravin; ++i) {
        vyspohyb[i].nazev = i;
    }

    for (int i = 0; i < POHYB; ++i) {
        if (pohyb[i].jedn == 2) {
            vyspohyb[pohyb[i].potr].myMnz = vyspohyb[pohyb[i].potr].myMnz + pohyb[i].mnoz.kg;
            vyspohyb[pohyb[i].potr].myJedn = pohyb[i].jedn;
        }
        else {
            vyspohyb[pohyb[i].potr].myMnz = vyspohyb[pohyb[i].potr].myMnz + pohyb[i].mnoz.kus;
            vyspohyb[pohyb[i].potr].myJedn = pohyb[i].jedn;
        }
    }
    for (int i = 0; i < pocetPotravin; ++i) {
        if (vyspohyb[i].myJedn == 2) {
            printf("%s %g kg \n", nazev[vyspohyb[i].nazev], vyspohyb[i].myMnz);
        }
        else {
            printf("%s %g ks \n", nazev[vyspohyb[i].nazev], vyspohyb[i].myMnz);
        }
    }
}

问题根源

核心问题是未初始化局部结构体数组vyspohyb的myMnz和myJedn成员:

  • 局部变量默认存储在栈内存中,栈内存的初始值是随机的垃圾数据
  • 在线编译器每次运行都会重置栈环境,垃圾值恰好不影响计算结果;而本地IDE(如VS、CLion)的栈复用机制会导致多次运行时垃圾值不一致,出现时好时坏的异常
  • 代码中仅初始化了nazev成员,myMnz(用于累加库存变动)和myJedn(存储单位)的初始值都是随机值,累加计算时会把垃圾值也包含进去,导致结果错误

修复方案

初始化vyspohyb数组的所有成员,将myMnz设为0(库存初始值为0),myJedn初始化为0(后续会被实际操作覆盖)。修复后的代码如下:

typedef enum { kus=1,kg } Jednotka;
typedef union { int kus; float kg; } Mnozstvi;
typedef enum { rohlik,chleb,brambory,sirup,merunky,cukr,cokolada,salam,mleko,kava,pivo,mouka,maso,sul,kmin,fazole,meloun } Potravina;
typedef struct { Potravina potr; Jednotka jedn; Mnozstvi mnoz; } Pohyb;

const Pohyb pohyb[]={{chleb,kg,{.kg=20}},{cukr,kg,{.kg=10}},{rohlik,kus,{.kus=70}},{cokolada,kus,{.kus=15}},{kava,kg,{.kg=2}},{mouka,kg,{.kg=5}},
                     {salam,kg,{.kg=6.5}},{mleko,kus,{.kus=30}},{brambory,kg,{.kg=40}},{merunky,kg,{.kg=8}},{sirup,kus,{.kus=18}},{mouka,kg,{.kg=5}},
                     {cukr,kg,{.kg=-1.5}},{cokolada,kus,{.kus=-2}},{brambory,kg,{.kg=-5}},{rohlik,kus,{.kus=-10}},{pivo,kus,{.kus=10}},
                     {kmin,kg,{.kg=.06}},{fazole,kg,{.kg=5}},{chleb,kg,{.kg=-1}},{mleko,kus,{.kus=-2}},{sirup,kus,{.kus=-1}},{pivo,kus,{.kus=25}},
                     {kava,kg,{.kg=6.5}},{mouka,kg,{.kg=-4}},{fazole,kg,{.kg=-.5}},{cukr,kg,{.kg=-2}},{cokolada,kus,{.kus=-3}},{sul,kg,{.kg=6}},
                     {brambory,kg,{.kg=-3.5}},{merunky,kg,{.kg=-.5}},{sirup,kus,{.kus=-3}},{mouka,kg,{.kg=5}},{pivo,kus,{.kus=-1}},
                     {mouka,kg,{.kg=-2}},{maso,kg,{.kg=10}},{maso,kg,{.kg=5.5}},{rohlik,kus,{.kus=-4}},{chleb,kg,{.kg=-3}},{rohlik,kus,{.kus=-35}},
                     {sirup,kus,{.kus=5}},{cokolada,kus,{.kus=-2}},{salam,kg,{.kg=-.3}},{merunky,kg,{.kg=-3}},{maso,kg,{.kg=-.5}},{maso,kg,{.kg=-.8}},
                     {meloun,kg,{.kg=22.5}},{meloun,kg,{.kg=-3.2}},{chleb,kg,{.kg=-.5}},{sirup,kus,{.kus=-1}},{mleko,kus,{.kus=-4}},{sul,kg,{.kg=-1}},
                     {rohlik,kus,{.kus=20}},{maso,kg,{.kg=-1.5}},{pivo,kus,{.kus=-8}}};

const unsigned POHYB=sizeof pohyb/sizeof *pohyb;

const char *nazev[]={"rohlik","chleb","brambory","sirup","merunky","cukr","cokolada","salam","mleko","kava","pivo","mouka","maso","sul","kmin","fazole","meloun"};

#include <stdio.h>

int main() {
    int pocetPotravin = sizeof nazev / sizeof nazev[0]; // 17
    typedef struct {
        Potravina nazev;
        float myMnz;
        Jednotka myJedn;
    } vysPohyb;
    vysPohyb vyspohyb[pocetPotravin];
    // 初始化所有成员:库存初始值设为0,单位初始化为0
    for (int i = 0; i < pocetPotravin; ++i) {
        vyspohyb[i].nazev = i;
        vyspohyb[i].myMnz = 0.0f;
        vyspohyb[i].myJedn = 0;
    }

    for (int i = 0; i < POHYB; ++i) {
        if (pohyb[i].jedn == kg) { // 用枚举常量替代魔法数字2,提升可读性
            vyspohyb[pohyb[i].potr].myMnz += pohyb[i].mnoz.kg;
            vyspohyb[pohyb[i].potr].myJedn = pohyb[i].jedn;
        }
        else {
            vyspohyb[pohyb[i].potr].myMnz += pohyb[i].mnoz.kus;
            vyspohyb[pohyb[i].potr].myJedn = pohyb[i].jedn;
        }
    }
    for (int i = 0; i < pocetPotravin; ++i) {
        if (vyspohyb[i].myJedn == kg) {
            printf("%s %g kg \n", nazev[vyspohyb[i].nazev], vyspohyb[i].myMnz);
        }
        else {
            printf("%s %g ks \n", nazev[vyspohyb[i].nazev], vyspohyb[i].myMnz);
        }
    }
    return 0;
}

额外优化说明

  • 将判断条件中的魔法数字2替换为枚举常量kg,避免硬编码,提升代码可读性和维护性
  • 使用+=运算符替代= a + b的写法,简化代码逻辑
  • 增加return 0;语句,符合C标准中main函数的返回规范

内容的提问来源于stack exchange,提问作者dejvoos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:50:33