【问题标题】:Pointers in C and castingC中的指针和强制转换
【发布时间】:2020-03-05 20:35:06
【问题描述】:

这次我开始学习指针了。我试图从这个数组中读取字节。任务几乎完成,但 CLang 不断警告我,警告我不明白。这是我的代码。 警告说:“函数调用参数是一个未初始化的值”

int main(void)
{
    int tab[] = {67305985,134678021,202050057};
    int *pp=0;
    pp=tab;

    char *wsk=(char*)pp;

    for (int i = 0; i < 12; i++)
    {
        if((wsk+i)!=(void*)NULL)
            printf("%d ",*(wsk+i));    // warning on this line
        else
            return 0;
    }

}

【问题讨论】:

  • (1) 不要发布代码图片。始终将您询问的代码作为文本发布。 (2) 我在发布的图像中只看到一个警告,并且它也很容易作为文本传达。
  • 在这种特殊情况下,我不得不不同意@JohnBollinger。发布代码图像的目的是显示内联警告。编辑后,生成未初始化值警告的位置就不太清楚了。此外,让图像显示另一个值得一提的警告,否则可能会被错过。
  • 在这种情况下,@Sniggerfardimungus,您应该查看how-to-ask,尤其是“请勿发布代码、数据、错误消息等的图像”部分(强调原文)。
  • @Sniggerfardimungus,它最初存在的方式可能比现在的方式略微更清晰,但使用起来要困难得多 .我们对问题格式的期望是有充分理由的,而且这个问题没有任何理由认为它应该是一个例外。
  • 我也想了一会儿,@FredK,但它也是错误的。同样,wsk 是指向char 的指针,最初指向tab 表示的十二个字节中的第一个。 *(wsk+i) 取消引用 一个 字节,而不是四个。取消引用对 OP 循环采样的所有 i 值有效。作为可变参数,结果值随后被提升为intprintf 因此接收到一个满足%d 指令的参数。

标签: c pointers casting


【解决方案1】:

这些警告来自 Clang 静态分析器(或者他们现在所说的任何东西)。

如果我们假设 int 至少有 4 个字节并且真实代码具有 #include &lt;stdio.h&gt; 并且没有其他更改,这对我来说似乎是一个误报。

如果您使用的是最新版本的分析器,您可以提交一份 clang 错误报告。好吧——如果他们允许还没有帐户的人提交错误报告,你就可以。也许阅读此线程的其他人可以做到。

注意:准确发布您正在运行的分析器的哪个版本将有助于解决问题(这可能与您用于构建的编译器不同——某些 IDE 使用不同的编译器进行构建,而不是这些内联消息) .

【讨论】:

  • 我正在使用 CLang 3.9
  • @Cnewbiec 可能会调查您是否可以升级用于消息的编译器版本(我不熟悉您使用的任何 IDE,因此无法提供更具体的建议)跨度>
  • @Cnewbiec 好的,也许看看你是否可以升级,我用 clang-tidy 搜索了 clion 的文档,它至少谈到了使用 clang 7.0.0。
  • Tbh 我无法更改验证系统使用的 CLANG。 :D 我的大学有这样的系统,我可以在其中发布我的代码。
  • @Cnewbiec 好的。我想您别无选择,只能在这些消息弹出时忽略它们,或者现在关闭分析器部分并不时将其重新打开。有时可能会破坏您的代码以安抚分析器,尽管在这种情况下我无法提供任何具体建议,您可以试错一些不同的代码变体来做同样的事情
【解决方案2】:

这个 if 语句

if((wsk+i)!=(void*)NULL)

没有意义。宏NULL 已经是一个空指针常量。因此,将其转换为 void * 是没有意义的。

并且指针wsk+i在这个循环中不能等于NULL,因为它最初指向一个对象。

只需去掉 if 语句,并在循环中输出每个字符。

在循环中使用像 12 这样的幻数是个坏主意。

你可以这样写

const size_t N = sizeof( tab ) / sizeof( *tab );

然后在循环中

for ( size_t i = 0; i < N * sizeof( int ); i++ )
//...

至于警告,如果您包含标题&lt;stdio.h&gt;,则它与呈现的代码无关。

【讨论】:

  • CLang 仍然给出与开始时相同的警告。我又附上了图片。
  • @Cnewbiec 正如我所写,删除 if 语句。我无法重现警告。
  • 已删除,但仍然存在。你认为我可以忽略这个警告吗?
  • @Cnewbiec 正如我所说,我无法重现警告。
  • sizeof tab 比再除以相同的值更简单:)
【解决方案3】:

wsk 永远不会为 null,因为您已将其设置为与 tab 相同(在 C/C++ 中,数组只是指向数据块的指针。警告告诉您无论如何您添加到wsk 的内容将始终为非空值。您需要做的是将循环中的迭代限制为数组中有效项的数量,因为 C/C++ 数组没有任何类型的终止符。

printf 可能只是让 CLang 感到困惑。试试printf("%d ", wsk[i]);

【讨论】:

  • 奇数。呃,为什么不呢? (该行应该按原样工作,但不够正统,可能会让 CLang 头疼。)
  • 我认为我的领导想教我们(我的团队)每一个细节。
  • 数组不是指针。它们是数据块。您可以创建指向任何对象的指针(无论是否为数组)。
  • printf("%d ", wsk[i]) 不会使警告消失。 (到目前为止)唯一能做的就是事先添加一个像printf("%p ", (void *) wsk); 这样的语句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多