当前位置 : 主页 > 编程语言 > c++ >

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

来源:互联网 收集:自由互联 发布时间:2021-06-23
我有一个文本文件,每行包含三列数据.前两个数字是整数,最后一个是双数,即 1 2 3.454 42 3.45... and so forth... 我使用以下C代码只读取文件中的第一行. #include stdio.h#include stdlib.hint main(void)
我有一个文本文件,每行包含三列数据.前两个数字是整数,最后一个是双数,即

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开关时,根本没有警告,我的代码可以正常运行而不会崩溃!

我使用的是英特尔2019编译器和Linux操作系统.

如果有人能帮我解决这个问题,我真的很感激.

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

这个错误恰好在没有通知的情况下通过,因为你明确地使用了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 ICC报告时

<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.1x和MSDOS 4.0以及Mac System 6的年龄相同.您也不会使用它们.请注意,即使是ICC 16.0.3之后的版本似乎也默认为C89模式.> ICC不是符合标准的C编译器.它在诊断方面实际上很糟糕.它接受-Wall作为“-Wno-more”的同义词是不可接受的.>因此,如果测试代码构建明显更快,则始终使用其他编译器进行开发和ICC.

网友评论