使用 macOS High Sierra 时在 C 中使用 while(free) 而不是 while(true)

Posted

技术标签:

【中文标题】使用 macOS High Sierra 时在 C 中使用 while(free) 而不是 while(true)【英文标题】:while(free) instead of while(true) in C whilst using macOS High Sierra 【发布时间】:2018-12-22 22:56:19 【问题描述】:

我最近在使用朋友 2017 MacBook Pro,运行 macOS High Sierra,为 Mac OSX 编译了 Code::Blocks 13.12。 (因为 Macintosh 版本自 2013 年以来未更新)。

在设置 Code::Blocks 时,macOS 需要从 Xcode 控制台工具安装 GCC,这是有道理的,但是当我开始在 Code::Blocks 中使用 while(true) 循环创建标准 C 控制台应用程序时。我得到一个错误,“true”在上下文中不起作用,但“free”这个词起作用了。果然,'while(free)' 确实可以运行和编译。

我尝试在谷歌上搜索免费是什么的解释,但似乎我是地球上唯一发现这种差异的人。 'free' 是 mac 特定的布尔变量吗,如果是,它的对立面是什么,它仍然是 'false' 吗?

任何答案将不胜感激。

【问题讨论】:

有人建议while (free),还是你随便选了一个词……? 这是我在尝试使用 'while(true)' 进行编译时收到的编译错误,我希望我能截取它的屏幕截图,我可能从现在开始的一天。 编译器可能在 spelling 中检测到“free”最接近“true”,但这绝对不意味着您应该使用它。 while (1)for (;;) 是正确的。 这个“X 没有被声明,也许你的意思是 Y?” GCC的特性没有复杂的逻辑。它只是查找名称与您使用的名称相似的标识。 GCC 建议 while (free) 只是因为它不知道 true 是什么,而 free 听起来足够相似。一般来说,GCC 提出的建议不一定能编译或正常工作。 @DanielH 可能。执行无限循环的经典 C 惯用方法是 for (;;) 【参考方案1】:

通常free 是[标准] 函数,用于通过malloc 等从堆中释放分配的内存。人。

调用它,你可以这样做:free(my_pointer)

但是,当你只是指定free [或任何其他函数] 没有任何括号,这意味着你想要地址 free 函数/符号本身的 em> [ 没有 实际调用/调用函数]。正常的“地址”运算符 [unary &](例如 &free)对于函数来说不需要,因为它对于像 int 这样的标量是必需的

free&free 生成相同的代码,但省略 & 更为惯用。

这是一个 调用 free 函数的 sn-p,并说明了仅使用不带括号的 free 的用法:

#include <malloc.h>

void *my_pointer;
void (*myfree)(void *);
void (*myfree2)(void *);

void
foo(void)


    // set pointer to function from the address of the free function
    myfree = free;

    // invoke the free function via indirect pointer
    (*myfree)(my_pointer);

    // this allows a pointer to function to behave syntactically like a
    // direct function call
    myfree(my_pointer);

    // set pointer to function from previous pointer to function
    myfree2 = myfree;

    // do the same thing as above
    myfree2(my_pointer);

为了好玩,您可以说:printf("%p\n",free) 并将其与您的程序的链接图进行比较。

由于[实际上]所有函数地址都不为零,因此执行while (free) 等效于while (&amp;free) 并且[如果在编译时未检测到/优化是一个稍慢的版本] 具有以下效果:while (1)

如果使用-Wall 编译,gcc 将产生:

warning: the address of ‘free’ will always evaluate as ‘true’ [-Waddress]
  while (free);
         ^~~~

【讨论】:

【参考方案2】:

许多 C 编译器试图使用类似于拼写检查器的东西来帮助猜测未声明标识符的适当替换。与大多数拼写检查器一样,这偶尔会产生有趣的结果,这就是其中之一。

如果您不使用#include &lt;stdbool.h&gt;,则不会定义true。另一方面,如果你执行#include &lt;stdlib.h&gt;,那么free 将被声明为一个函数。

C 的标准转换意味着函数会自动转换为函数指针,函数指针可以自动转换为布尔值。所以你绝对可以在布尔表达式中使用函数名,它将被转换为真值。

如果你仔细看freetrue,你会注意到它们的相似之处:它们的元音和辅音在同一个地方,四个字母中有两个是相同的;此外,f 看起来很像t(并且,如评论中所述,它位于键盘附近)。因此,拼写检查器可能会猜测 truefree 的拼写错误。

建议试图重现这个奇怪警告的人回想一下,OP 使用的是 Mac,Mac 上的默认开发环境使用 Clang 作为其 C/C++ 编译器,并将 gcc 别名为 clang ,想必是因为很多人认为你使用gcc命令编译。 (提示:c99 由 Posix 指定。)

所以这里是所有荣耀的警告(伴随着另一个有用的警告,因为我用-Wall编译:

<stdin>:4:9: error: use of undeclared identifier 'true'; did you mean 'free'?
  while(true) 
        ^~~~
        free
/usr/include/stdlib.h:563:13: note: 'free' declared here
extern void free (void *__ptr) __THROW;
            ^
<stdin>:4:9: warning: address of function 'free' will always evaluate to 'true' [-Wpointer-bool-conversion]
  while(true) 
  ~~~~~ ^~~~
<stdin>:4:9: note: prefix with the address-of operator to silence this warning
  while(true) 
        ^
        &
1 warning and 1 error generated.

注意:输入的第 4 行已引用。第 2 行是#include &lt;stdlib.h&gt;stdbool.h 未导入。

(另外,如果你碰巧遇到它,你可以使用 gcc-8 生成类似的拼写检查建议。但我很确定 OP 正在使用 clang。)

【讨论】:

我怀疑任何拼写检查器都足够复杂,可以查看字母形状,而且很可能不会注意到元音/辅音。也许它注意到ft 在 QWERTY 中是用同一个手指输入的,但我对此表示怀疑。 (并且 OP 说 Code::Blocks 安装了 GCC;它对你的谎言太多以至于即使你明确要求安装 GCC 它也会给你 Clang ?) 看起来 GCC 只会在您“修复错字”后显示第二个警告。 @DanielH:他没有这么说。他说“在设置 Code::Blocks 时,macOS 需要从 Xcode 控制台工具安装 GCC”,而 Xcode 控制台工具,正如我所指出的,将安装 clang然后称它为 gcc。 (它也被称为“clang”和“c99”。)如果你以后真的安装gcc,那么你将有两个编译器。但是你不会从 Xcode 工具中得到它。 另外,您会惊讶于拼写检查算法的复杂程度。他们仍然会犯滑稽的错误。 :) 他们肯定认为仅元音不同的单词比具有显着辅音差异的单词更接近,通常是因为他们尝试使用语音比较。考虑字母形状的那些对于校正 OCR 文件很重要。 是的,我希望 OCR 考虑字母形状,但除非有大量的 OCRed C 代码,否则我不希望 Clang 或 GCC 考虑它。数值和手指位置更合理,但我仍然敢打赌,这主要是基于共享的一半字母。不过现在我很好奇,看看我是否真的能找到它。【参考方案3】:

在 C 中,true 不是内置标识符,而是only declared in &lt;stdbool.h&gt;。如果您不包含它,则 true 未定义。这可能是 Code::Blocks 或它所称的东西如何混淆的一部分。出于某种原因,它认为truefree 的拼写错误。不是;你的意思是true,它提出了一个不好的建议。

当您尝试while (free) 时发生的情况是编译器看到了function free,发现您没有将它作为函数调用,并将其转换为function pointer。一个函数指针在它不是NULL 时作为真,而这个指针指向free,所以它像while (true) 一样工作。

如果您包含&lt;stdlib.h&gt;,那么编译器将能够使用free 进行编译,您将获得无限循环。如果你没有,我不知道为什么while (free) 会起作用;我不能让这种事情发生在我身上。

【讨论】:

【参考方案4】:

嗯,true 在 C 中是一个非常普通的标识符。它 不是 一个布尔文字。如果您使用 C99 或更高版本,并且想要标准布尔类型,请查看 &lt;stdbool.h&gt;

free()&lt;stdlib.h&gt; 中定义的函数。在它衰减为指针的布尔上下文中使用它,就像任何其他指向函数或对象的指针一样,它不是NULL,因此足够真实。

除此之外,(编译器?)暗示替代方案当然很好奇。

用 C 语言做你想做的事的惯用方式是 for (;;)(发音为“forever”),尽管 while(1) 和无数其他人也可以。

【讨论】:

但这需要将“free()”定义为“free”作为运算符。不是方法,也不是别的。否则你会输入'while(free())' 我相信。 @NaturalistUbuntu 稍微阐述了机制。

以上是关于使用 macOS High Sierra 时在 C 中使用 while(free) 而不是 while(true)的主要内容,如果未能解决你的问题,请参考以下文章

如何制作macos high sierra安装u盘

下载macOS high sierra失败,使用已购页面再试一次怎么弄

MacOS High Sierra 和 X11 转发

2011年的macos+high+sierra如何更新系统?

如何以编程方式在 macOS Sierra/High Sierra 上创建 PPTP *** 连接?

无法从源 MacOS High Sierra 构建 TensorFlow