在IF语句中有很多条件时,是否有任何基于C99标准的限制或缺点,如果有,是什么?

zz2j4svz  于 2023-04-19  发布在  其他
关注(0)|答案(3)|浏览(84)

我做了一个for循环,在每次迭代中检查索引是否等于整数,我意识到我可以写一个很长的if语句,使它比现在更可读。
我想知道在if语句中包含100个条件是否有任何明确的规则或未定义的行为、限制或缺点:

  1. &&
  2. ||
    根据C99标准,在具有最新gcc的现代x64 Intel机器上编译。
9avjhtql

9avjhtql1#

我想知道根据C99标准在if语句中有100个条件是否有任何明确的规则或未定义的行为、限制或缺点
不,没有明确的规则或未定义的行为。(有很多限制和缺点,在这个问题的其他答案和评论中详细讨论过,但这些都是风格,不是编译器会关心的任何东西。
在现代x64 Intel机器上编译,带有最新的gcc
如果你的问题是关于C99标准定义的语言,那么你使用的编译器并不重要。
一方面,这对计算机程序来说并不罕见(包括编译器)有各种限制,不能对完全无界的输入进行操作。但另一方面,它一直在某种程度上是C哲学的一部分,绝对是GNU/FSF哲学的一部分,尽可能地避免任何和所有任意的限制。所以如果我听到gcc有你所问的那种限制,我会非常惊讶。
我构造了一个“简单的”if语句,其格式如下:

if(a1 == b1 && a2 == b2 && a3 == b3 && … && a98 == b98 && a99 == b99 && a100 == b100)

我在gcc的两个版本(4.6.3和10.2.1)下测试了它,有-std=c99和没有-std=c99,没有得到任何错误(但我没有测试生成的代码以确保它完美地工作)。
正如Eric Postpischil在他的回答中提到的,如果一个编译器编译了一个没有错误的复杂表达式,但是生成了行为不正确的代码,这将是非常令人惊讶的。这是(谢天谢地)在实践中罕见的失败模式。

hpcdzsge

hpcdzsge2#

我想知道是否有任何明确的规则或未定义的行为,限制,…
C 1999 5.2.4 1说:“翻译和执行环境都限制了语言翻译器和库的实现......”这意味着编译器不需要能够编译每一个理论上符合任何长度的C程序。当给定的程序包含太多复杂的各种类型时,它可能会失败。
5.2.4.1 1指定了符合C实现必须能够支持的最小阈值,尽管指定的很弱,因为实现应该能够翻译和执行一个满足所有阈值的程序。这些阈值都与具有100个条件的if没有直接关系。可能影响它的两个是:

  • 完整表达式中带括号的表达式的63个嵌套级别
    ...
  • 逻辑源行中有4095个字符
    在你的问题中不要提到括号,通过将语句分成多行,很容易避免在逻辑源代码行中出现4095个字符。
    ......在if语句中有100个条件的缺点是由......
    这里的主要问题不是编译器的限制或缺陷,而是糟糕的设计。我对编译器的最低要求是,如果它不能正确编译程序,它会报告。我们应该能够期望,如果编译器生成一个程序,而没有报告编译错误,那么生成的程序将正确执行。
    此外,高质量的编译器可能会优化程序并为if语句生成好的代码,可能比作者名义上写的更好。
    然而,在一般的编程中,优化和表达的机会比比皆是。一个有100个条件的if语句可能有很多替代设计的可能性。我们可以使用表格来记录和查找哪些情况应该通过或失败测试,而不是将它们硬编码到代码中。或者我们可以使用其他数据驱动的解决方案,比如一个表示待测试条件的树。我们可能会优化测试,尝试首先区分最常见的情况。我们可能会对条件进行数学分析,以简化它们。我们可能会重写条件,使其对人类读者更清晰。
hgqdbh6s

hgqdbh6s3#

C标准怎么说

C99和C11标准(C99 §5.2.4.1平移限值;C11 §5.2.4.1平移限值)表示:
该实现应能够翻译和执行至少一个程序,该程序至少包含以下限制中的每一个的一个示例:

  • 127块的嵌套层级
  • 63个嵌套级别的条件包含
  • 12个指针、数组和函数声明符(任意组合),用于修改声明中的算术、结构、联合或void类型
  • 完整声明符中带括号的声明符的63个嵌套级别
  • 完整表达式中带括号的表达式的63个嵌套级别
  • 内部标识符或宏名称中的63个有效初始字符(每个通用字符名称或扩展源字符被视为单个字符)
  • 外部标识符中的31个有效初始字符(指定短标识符0000 FFFF或更少的每个通用字符名称被视为6个字符,指定短标识符00010000或更多的每个通用字符名称被视为10个字符,并且每个扩展源字符被视为与对应的通用字符名称相同的字符数(如果有的话)19)
  • 一个翻译单元中有4095个外部标识符
  • 在一个块中声明了511个具有块范围的标识符
  • 在一个预处理翻译单元中同时定义4095个宏标识符
  • 一个函数定义中包含127个参数
  • 一个函数调用中有127个参数
  • 一个宏定义中包含127个参数
  • 一次宏调用中有127个参数
  • 逻辑源行中有4095个字符
  • 4095个字符串文字(串联后)
  • 对象中的65535字节(仅在托管环境中)
  • #included文件的15个嵌套级别
  • switch语句的1023个case标签(不包括任何嵌套 * switch语句的case标签)
  • 1023个成员在一个单一的结构或工会
  • 单个枚举中有1023个枚举常量
  • 单个结构声明列表中的63级嵌套结构或联合定义

18)实现应该尽可能避免强加固定的转换限制。
脚注19指出了关于标识符最大长度的“未来方向”,指出任何小于255的长度都应被视为过时。
同样的限制适用于C18(C17)和C23的最新草案。
这些限制都不直接适用于您所描述的场景,在描述你的场景的范围内。最有可能应用的是“完整表达式中括号表达式的63个嵌套级别”。“逻辑行长度”限制可以通过在标记对之间添加换行符来规避。只是不要创建任何长于行长度限制的标识符-但是标识符将是完整的论文,因此完全不切实际。整个答案只有4KiB多一点。
因此,即使是一个非常复杂的if条件,编译器也不太可能有任何问题。“只有”100个条件不太可能破坏它。
然而,任何人如果能理解一个if条件中包含100个条件的代码,那他就是一个奇迹创造者(或者可能是一个骗子)。

if (strcmp(a, "ABC") == 0 ||
    strcmp(a, "BCD") == 0 ||
    …
   )

如果条件非常多样化,或者如果有嵌套的条件(||&&的混合,加上括号,可能还有一些否定运算符),那么人们就不会理解代码。

别这么做!

IMNSHO,你的座右铭应该是“不要这样做!”必须有更好的方法来处理你正在测试的任何东西。替代方法包括循环和函数。编译器限制应该很少,如果有的话,是你关心的。当他们关心时,通常有某种代码结构问题。例如,如果你有一个需要128个参数的函数,而你的编译器遵循标准规定的下限(127),那么你的数据结构化得不是很好-你可能应该使用结构类型来将其中的一些参数组合在一起。

相关问题