多写了几句看似多余的代码,就让得分从0分上升至100分,这是何奥秘?

P1563 [NOIP2016 提高组] 玩具谜题

编译器认为两段代码都是错的: ```plain main.cpp: In function 'int main()': main.cpp:6:33: warning: format '%d' expects argument of type 'int*', but argument 2 has type 'bool*' [-Wformat=] 6 | for(int i=0;i<n;i++)scanf("%d%s",&l[i].t,l[i].c); | ~^ ~~~~~~~ | | | | int* bool* main.cpp:9:17: warning: format '%d' expects argument of type 'int*', but argument 2 has type 'bool*' [-Wformat=] 9 | scanf("%d%d",&a,&s); | ~^ ~~ | | | | int* bool* ```
by ud2_ @ 2022-12-10 16:56:21


请不要使用 `scanf` 读入 `bool` 类型的变量,可以使用 `cin` 或者把 `bool` 改成 `int`。
by Anamnesis @ 2022-12-10 16:59:05


@[ud2_](/user/206953) 是吗?看来我的编译器和你的编译器不一样。你觉得这与m值的改变有关系吗?看来我下次不要冒险了。
by Herman526 @ 2022-12-10 17:25:35


@[Herman526](/user/786834) 不是编译器不一样——试试在编译选项中加上 `-Wall`,三大主流编译器都[会](https://godbolt.org/z/nhf1sfq38)[报](https://godbolt.org/z/8M4ahsYMW)[错](https://godbolt.org/z/Y9K8vG54o)。 > 这与 m 值的改变有关系吗? 因为是[未定义行为](https://zh.cppreference.com/w/cpp/language/ub)所以会发生离奇的事。可以[在这里找到相关规定](https://eel.is/c++draft/basic.lval#11)。
by ud2_ @ 2022-12-10 20:35:07


@[ud2_](/user/206953) 的确,我在Dev-C++中看到过类似的设置,明天我来尝试一下。
by Herman526 @ 2022-12-10 20:40:14


### 根据大家的讨论,我进行了一番尝试。 --- @[ud2_](/user/206953) : >不是编译器不一样——试试在编译选项中加上 `-Wall`,三大主流编译器都会报错。 我尝试了一下,的确没错,看来以后开启此选项能避免更多的意外错误。 --- @[ABANDONED_ACCOUNT](/user/392400) : >请不要使用 `scanf` 读入 `bool` 类型的变量,可以使用 `cin`。 换成`cin`后,程序可以AC,但效率较低,可能是因为流输入较慢。 --- **但是,我仍有一个疑问:** 我将两处`bool`改成`char`(因为其占用空间最小)后,编译器不出意外的产生了`[Warning]`警告,代码不能AC。`scanf`本是可以读入`char`的,可编译器仍产生错误,也许是因为“**未定义行为**”会带来很大的影响。可既然如此,前面的`scanf`中也应该出现错误,而电脑仍能乖乖地接收数据。 ### 为什么“未定义行为”在此时未带来影响?有具体的原因吗?
by Herman526 @ 2022-12-11 16:15:17


@[Herman526](/user/786834) **未定义行为**顾名思义就是可能造成任何神奇的结果,既可能造成影响也可能不造成影响,也可能现在不造成影响、在其它地方却造成影响。 `scanf` 读入 `char` 的占位符是 `%c`,而不是 `%d`。 `scanf` 从来就不能被用于读入 `bool`,这是完全错误的用法。
by Anamnesis @ 2022-12-11 16:43:24


我明白了,“**未定义行为**”就是个随机事件,要么默默无闻,要么成为程序出错的罪魁祸首。我得多多注意编译器的`[Warning]`警告,它们可能是我发现程序错误的帮手。 **非常感谢大家告诉我该问题的答案,让我及时发现了写代码的大忌!**
by Herman526 @ 2022-12-11 16:53:04


@[Herman526](/user/786834) > 为什么“未定义行为”在此时未带来影响? UB 总是会在意料之外的地方出现错误(或者不出现错误),仅仅是给“耐心接受全部数据”的程序加上 `-O2` [它就会 RE](/record/97116398)。 一些编译器[提供运行时查错的选项](https://godbolt.org/z/P5E73Wedq)。 > 编译器仍产生错误。 如果还用 `%d` 那么必然因为类型不匹配而出现 UB,因此编译器会正确地报警告。 `char` 对应的“十进制整数”格式是 `%hhd` / `%hhu`。编译器也会对它报警告,或许是想强调“`char` 是独立于 `signed char` 和 `unsigned char` 以外的类型”,但它确实可以 AC。 > 可能是因为流输入较慢。 ```cpp std::ios_base::sync_with_stdio(false); ``` 在 `main` 开头加上这样一行,`cin` 就没那么慢了,输入量大时 `cin` 还可能更快。需要注意这样做之后不能再在同一个流上混用 C 和 C++ 的 IO 方式(比如,`cin` 和 `scanf`,或者 `cout` 和 `puts`)。
by ud2_ @ 2022-12-11 17:28:04


@[ud2_](/user/206953) 根据你的建议,我在本地程序前加上了`#pragma GCC optimize(2)`(据说这是开启-O2优化的指令),的确程序执行完`scanf("%d%d",&a,&s)`后,就停止工作了。在洛谷评测机上开启“O2优化”后,程序的确RE了。 不过,我的疑问又随之而来:**既然网上说“-O2优化能使程序的编译效率大大提升,从而减少程序的运行时间,达到优化的效果”,那么“-O2优化”就应该让程序质量更加高,而事实却让程序里的“未定义行为”暴露无遗。这又是什么奥秘呢?**
by Herman526 @ 2022-12-11 18:46:26


| 下一页