jjzjj

关于C#:getc是宏还是函数?

codeneng 2023-03-28 原文

Is getc a macro or a function?

我试图找出getcfgetc 之间的区别。当时我看到这样的说法:

The difference between getc and fgetc is that getc can be implemented as a macro, whereas fgetc cannot be implemented as a macro.

那么,getc 真的是一个函数还是一个宏?如果是宏,它会调用其他函数。那么,getc 是否在 C 中实现?

  • 这取决于你的 C 库,真的。 getc() 可以实现为宏……也可以不实现,这可能会在未来发生变化。
  • 所以,它不是像 fgetc、fgets 那样的独特功能。是写吗?


The difference between getc and fgetc is that getc can be implemented as a macro, whereas fgetc cannot be implemented as a macro.

那是不正确的。

除了少数例外,任何 C 标准库函数都可以另外实现为宏,但该宏的编写方式存在一些限制(因此宏仍可以像函数一样使用)。

引用 N1570 第 7.1.4 节:

Any function declared in a header may be additionally implemented as a
function-like macro defined in the header, [...] Any invocation of a
library function that is implemented as a macro shall expand to code
that evaluates each of its arguments exactly once, fully protected by
parentheses where necessary, so it is generally safe to use arbitrary
expressions as arguments.

getc 的特别之处在于其中一项限制可以放宽(7.21.7.5):

The getc function is equivalent to fgetc, except that if
it is implemented as a macro, it may evaluate stream more than
once, so the argument should never be an expression with side effects.

fgetcgetc的声明是:

1
2
int fgetc(FILE *stream);
int getc(FILE *stream);

stream 参数(例如,在像 fgetc(stdin)getc(file) 这样的调用中几乎总是一个没有副作用的表达式,但规则仍然禁止将 fgetc 定义为对其参数求值超过一次,以防程序员编写类似 fgetc(file_list[i++]) 之类的东西。对于 getc,该规则被放宽,以便可以将其定义为宏(在某些情况下可以显着提高效率),同时可能会破坏类似 .

fgetc 的情况下,将其实现为宏而不是仅仅作为函数可能不会有太多优势。关键是标准明确允许它。

So, is getc implemented in C or not?

也许吧。任何 C 库函数都不需要在 C 中实现。某些函数可以用汇编程序或任何其他语言实现 - 或者它们可能是编译器内在函数。通常大多数或所有 C 标准库函数都是用 C 实现的,但标准只指定它们的工作方式,而不是它们的编写方式。


getc 是 C99 标准第 7.21.7.5 节中所述的函数,可能会或可能不会作为宏实现:

The getc function is equivalent to fgetc, except that if it is implemented as a macro, it may evaluate stream more than once, so the argument should never be an expression with side effects.

它不适用于具有副作用的参数。例如 --

1
int c = getc(*fpp++);

  • 所以,这取决于C的版本
  • @mohan:不,它不依赖于 C 的版本。标准对 fgetcgetc 的描述在 C90、C99 和 C11 中基本相同。
  • @mohan 不,它不会依赖于 C 的版本。
  • fgetc,可以实现为宏。关于如何编写该宏有更多限制。有关详细信息,请参阅我的答案。
  • @KeithThompson fgetc 可以实现为宏吗?
  • @ameyCU:任何标准 C 库函数都可以实现为宏。在 fgetc 的情况下可能没有太多理由这样做,但这是允许的。看我的回答。

有关关于C#:getc是宏还是函数?的更多相关文章

  1. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  2. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  3. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  4. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  5. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  6. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  7. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  8. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  9. ruby-on-rails - 将字符串转换为 ruby​​-on-rails 中的函数 - 2

    我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。

  10. ruby-on-rails - Ruby 流量控制 : throw an exception, 返回 nil 还是让它失败? - 2

    我在思考流量控制的最佳实践。我应该走哪条路?1)不要检查任何东西并让程序失败(更清晰的代码,自然的错误消息):defself.fetch(feed_id)feed=Feed.find(feed_id)feed.fetchend2)通过返回nil静默失败(但是,“CleanCode”说,你永远不应该返回null):defself.fetch(feed_id)returnunlessfeed_idfeed=Feed.find(feed_id)returnunlessfeedfeed.fetchend3)抛出异常(因为不按id查找feed是异常的):defself.fetch(feed_id

随机推荐