草庐IT

c++ - C 预处理器在多大程度上考虑整数文字后缀?

coder 2023-11-13 原文

今天,我偶然发现了这样的事情:

#define FOO 2u

#if (FOO == 2)
  unsigned int foo = FOO;
#endif

不管代码为何如此(让我们不要质疑为什么),我想知道预处理器甚至可以在多大程度上处理整数文字后缀。我真的很惊讶它能起作用。 用 GCC and C99 做了一些实验后使用此代码...

#include <stdio.h>

int main()
{
  #if (1u == 1)
    printf("1u == 1\n");
  #endif

  #if (1u + 1l == 2ll)
    printf("1u + 1l == 2ll\n");
  #endif

  #if (1ull - 2u == -1)
    printf("1ull - 2u == -1\n");
  #endif

  #if (1u - 2u == 0xFFFFFFFFFFFFFFFF)
    printf("1u - 2u == 0xFFFFFFFFFFFFFFFF\n");
  #endif

  #if (-1 == 0xFFFFFFFFFFFFFFFF)
    printf("-1 == 0xFFFFFFFFFFFFFFFF\n");
  #endif

  #if (-1l == 0xFFFFFFFFFFFFFFFF)
    printf("-1l == 0xFFFFFFFFFFFFFFFF\n");
  #endif

  #if (-1ll == 0xFFFFFFFFFFFFFFFF)
    printf("-1ll == 0xFFFFFFFFFFFFFFFF\n");
  #endif
}

... 仅打印所有语句:

1u == 1
1u + 1l == 2ll
1ull - 2u == -1
1u - 2u == 0xFFFFFFFFFFFFFFFF
-1 == 0xFFFFFFFFFFFFFFFF
-1l == 0xFFFFFFFFFFFFFFFF
-1ll == 0xFFFFFFFFFFFFFFFF

...我猜预处理器完全忽略了整数文字后缀,并且可能总是以 native 整数大小(在本例中为 64 位)进行算术和比较?

所以,这是我想知道的东西:

  1. 预处理器在多大程度上考虑整数文字后缀?还是只是忽略它们?
  2. 是否存在任何依赖关系或不同环境的不同行为,例如不同的编译器、C 与 C++、32 位与 64 位机器等?即,预处理器的行为取决于什么?
  3. 所有指定/记录的内容在哪里?

想自己了解一下,查了一下 Wikipediathe C standard (working paper) .我找到了有关整数后缀的信息和有关预处理器的信息,但没有找到有关这些组合的信息。显然,我也用谷歌搜索了它,但没有得到任何有用的结果。

我看过this Stack Overflow question这阐明了应该指定的位置,但是,我找不到问题的答案。

最佳答案

C 2018 6.10.1 处理条件包含( #if 和相关语句以及 defined 运算符)。第 1 段说:

The expression that controls conditional inclusion shall be an integer constant expression except that: identifiers (including those lexically identical to keywords) are interpreted as described below; and it may contain unary operator expressions of the form

defined identifier

or

defined ( identifier )

整型常量表达式在6.6 6中定义:

An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.

该段一般适用于 C,而不仅仅是预处理器。所以可以出现在#if中的表达式语句与通常出现在 C 中的整数常量表达式相同。但是,如上面引述中所述,sizeof_Alignof只是标识符;它们不被识别为 C 运算符。特别是,6.10.1 4 告诉我们:

… After all replacements due to macro expansion and the defined unary operator have been performed, all remaining identifiers (including those lexically identical to keywords) are replaced with the pp-number 0,…

那么,哪里 sizeof_Alignof出现在 #if表达式,它变成0 .因此,一个 #if表达式只能有常量操作数和 defined表达式。

第4段接着说:

… The resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>.…

6.6 是常量表达式部分。

因此,编译器将接受 #if 中的整数后缀表达式,并且不依赖于 C 实现(对于核心 C 语言中所需的后缀;实现可以允许扩展)。但是,将使用 intmax_t 执行所有算术运算。或 uintmax_t ,而这些确实取决于实现。如果您的表达式不依赖于高于最小要求1 的整数宽度,则它们在任何 C 实现中的计算都应该相同。

此外,第 4 段继续说字符常量和值可能会有一些变化,我在这里省略,因为它与这个问题无关。

脚注

1 intmax_t指定能够表示任何有符号整数类型的任何值的有符号类型 (7.20.1.5 1),以及 long long int是必须至少为 64 位 (5.2.4.2.1 1) 的有符号类型,因此任何符合标准的 C 实现都必须在预处理器中提供 64 位整数运算。

关于c++ - C 预处理器在多大程度上考虑整数文字后缀?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56244247/

有关c++ - C 预处理器在多大程度上考虑整数文字后缀?的更多相关文章

  1. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  2. ruby - 如何使用文字标量样式在 YAML 中转储字符串? - 2

    我有一大串格式化数据(例如JSON),我想使用Psychinruby​​同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  5. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. ruby - 在 Ruby 中将整数格式化为固定长度的字符串 - 2

    有没有一种简单的方法可以将给定的整数格式化为具有固定长度和前导零的字符串?#convertnumberstostringsoffixedlength3[1,12,123,1234].map{|e|???}=>["001","012","123","234"]我找到了解决方案,但也许还有更聪明的方法。format('%03d',e)[-3..-1] 最佳答案 如何使用%1000而不是进行字符串操作来获取最后三位数字?[1,12,123,1234].map{|e|format('%03d',e%1000)}更新:根据theTinMan的

  8. ruby - 如何搜索、递增和替换 Ruby 字符串中的整数子字符串? - 2

    我有很多这样的文档:foo_1foo_2foo_3bar_1foo_4...我想通过获取foo_[X]的所有实例并将它们中的每一个替换为foo_[X+1]来转换它们。在这个例子中:foo_2foo_3foo_4bar_1foo_5...我可以用gsub和一个block来做到这一点吗?如果不是,最干净的方法是什么?我真的在寻找一个优雅的解决方案,因为我总是可以暴力破解它,但我觉得有一些正则表达式技巧值得学习。 最佳答案 我(完全)不懂Ruby,但类似这样的东西应该可以工作:"foo_1foo_2".gsub(/(foo_)(\d+)/

  9. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

  10. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

随机推荐