gpt4 book ai didi

使用 ICC 编译的代码使用 -O2,关于 strtok 的警告和使用 -O1 的崩溃

转载 作者:太空狗 更新时间:2023-10-29 15:23:09 28 4
gpt4 key购买 nike

我有一个文本文件,每行包含三列数据。前两个数字是整数,最后一个是 double ,即

1 2 3.45
4 42 3.45
... and so forth...

我正在使用以下 C 代码从文件中读取仅第一行

#include <stdio.h>
#include <stdlib.h>

int main(void) {
long int m, n;
double val;
FILE* f = fopen("input.txt", "r");
char line[1024];
char* pch;
fgets(line, sizeof(line), f);
pch = strtok(line, " \t"); //** warning
n = strtol(pch, NULL,10);
pch = strtok(NULL, " \t"); //** warning
m = strtol(pch, NULL,10);
pch = strtok(NULL, " \t"); //** warning
val = strtod(pch, NULL);
...
}

但是,当我尝试使用 -std=c89 -Wall -Wextra -O1 开关编译代码时,我收到每个 的以下警告消息strtok 并且程序因段错误而崩溃:

<source>(9): warning #556: a value of type "int" cannot be assigned to an entity
of type "char *"

pch = strtok(line, " \t");
^
...
Compiler returned: 0

但是当我尝试 -O2-O3 开关时,根本没有警告,我的代码也没有崩溃!

我使用的是 Intel 2019 编译器和 Linux 操作系统。

如果有人能帮助我解决这个问题,我将不胜感激。

最佳答案

原因是你忘记了#include <string.h>它定义了 strtok 的原型(prototype)!

这个 bug 碰巧在没有通知的情况下通过了,只是因为你明确地使用了 C89 模式并且因为 C89 允许隐式函数声明(假设未声明的函数返回一个 int) 而且因为英特尔 C 编译器有问题!


我已将代码简化为:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
FILE* f = fopen("foo", "r");
char line[1024];
char* pch;
fgets(line, sizeof(line), f);
pch = strtok(line, " \t");
}

compiled with -std=c89 and -O1 国际商会报告

<source>(9): warning #556: a value of type "int" cannot be assigned to an entity 
of type "char *"

pch = strtok(line, " \t");
^

如果compiled with -O2 警告消失了!但这不符合 C89 3.3.16.1 Simple assignment上面写着

Constraints

One of the following shall hold: [42]

  • the left operand has qualified or unqualified arithmetic type and the right has arithmetic type;

  • the left operand has a qualified or unqualified version of a structure or union type compatible with the type of the right;

  • both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;

  • one operand is a pointer to an object or incomplete type and the other is a pointer to a qualified or unqualified version of void, and the type pointed to by the left has all the qualifiers of the type pointed to by the right; or

  • the left operand is a pointer and the right is a null pointer constant.

5 个项目符号均不匹配。由于违反了约束,兼容的编译器必须发出诊断消息,ICC 不会这样做


但是,您是否应该使用 -std=c11模式,even on -O2 level编译器将为真正的罪魁祸首输出诊断信息:

<source>(9): warning #266: function "strtok" declared implicitly

pch = strtok(line, " \t");
^

Compiler returned: 0

在缺少 strtok 的现有声明的情况下编译器使用 C89 规则进行隐式函数声明,并隐式假定该函数将被声明为

int strtok();

但这违反了不再有隐式函数声明的 2011 修订版,因此会输出诊断消息。


最后应该指出的是,ICC 诊断真的非常糟糕。如果你使用 -std=c89 -O2 -Wall -Wextra对于我的节目摘录,你still receive no warnings whatsoever !

主要要点是:

  • 永远不要使用 C89 模式。它是 30 岁。它与 Windows 2.1xMSDOS 4.0 以及 Mac System 6 同龄。你也不会使用它们。 请注意,即使是晚至 ICC 16.0.3 的版本似乎也默认为 C89 模式。

  • ICC 不是符合标准的 C 编译器。它实际上在诊断方面不好。它接受 -Wall作为 "-Wno-more " 的同义词是 Not Acceptable 。

  • 因此,如果明显更快,请始终使用其他编译器进行开发,而 ICC 仅用于经过测试的代码构建。

关于使用 ICC 编译的代码使用 -O2,关于 strtok 的警告和使用 -O1 的崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55347937/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com