getc是如何定义的?

getc是如何定义的?,c,C,我听说getc,与fgetc不同,它是一个宏,我想检查一下。我在哪里可以找到getc的源代码?我相信这部分说明了一切: getc函数相当于fgetc,只是如果它是作为宏实现的,它可能会多次计算流,因此参数不应该是具有副作用的表达式 这样做: // a function that does some side effects // and also returns a FILE* FILE *func_that_returns_file(); int main() { getc(func_

我听说
getc
,与
fgetc
不同,它是一个宏,我想检查一下。我在哪里可以找到
getc
的源代码?

我相信这部分说明了一切:

getc函数相当于fgetc,只是如果它是作为宏实现的,它可能会多次计算流,因此参数不应该是具有副作用的表达式

这样做:

// a function that does some side effects
// and also returns a FILE*
FILE *func_that_returns_file();

int main() {
   getc(func_that_returns_file())
}

是不允许的,因为它可能多次调用函数。

如注释中所述,
getc
可以但不需要作为宏实现。相反,它必须有一个功能实现。所有这些都不是特定于
getc
。根据C99规范第7.1.4/1节:

头中声明的任何函数都可以作为头中定义的类似于宏的函数来实现,因此,如果在包含库函数的头时显式声明库函数,则可以使用以下技术之一确保声明不受此类宏的影响。函数的任何宏定义都可以通过将函数名括在括号中来局部抑制,因为该函数名后面不跟左键 表示宏函数名扩展的括号。出于同样的语法原因,允许它获取库函数的地址,即使它也被定义为宏

因此,事实上,虽然C实现可能选择将某些库函数实现为宏,但它还必须提供非宏实现,以便它们可以用作函数指针(例如,如果要将
getc
作为参数传递给另一个函数)


我们知道fgetc和getc的区别在于第一个是函数,第二个是宏

我们不知道这一点,因为这不是真的。C实现必须将C标准库中指定的每个函数定义为实际函数。1 C实现也可以将任何函数定义为类似宏的函数。即使实现为任何标准库函数提供宏,它也必须提供实际函数

因此,
getc
的函数声明出现在
stdio.h
中(直接在其中或间接地在它包含的某些文件中)
stdio.h
还可以使用
#define
包含
getc
的定义

脚注
1这适用于要求实施提供的功能;某些标题或函数在各种情况下是可选的。

发件人:
https://code.woboq.org/userspace/glibc/libio/getc.c.html

getc()
的源代码是:

/* Copyright (C) 1993-2019 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.
   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.
   As a special exception, if you link the code in this file with
   files compiled with a GNU compiler to produce an executable,
   that does not cause the resulting executable to be covered by
   the GNU Lesser General Public License.  This exception does not
   however invalidate any other reasons why the executable file
   might be covered by the GNU Lesser General Public License.
   This exception applies to code released by its copyright holders
   in files containing the exception.  */
#include "libioP.h"
#include "stdio.h"
#undef _IO_getc
int
_IO_getc (FILE *fp)
{
  int result;
  CHECK_FILE (fp, EOF);
  if (!_IO_need_lock (fp))
    return _IO_getc_unlocked (fp);
  _IO_acquire_lock (fp);
  result = _IO_getc_unlocked (fp);
  _IO_release_lock (fp);
  return result;
}
#undef getc
weak_alias (_IO_getc, getc)
weak_alias (_IO_getc, fgetc)
#ifndef _IO_MTSAFE_IO
#undef getc_unlocked
weak_alias (_IO_getc, getc_unlocked)
weak_alias (_IO_getc, fgetc_unlocked)
#endif
<代码> /* Copyright(c)1993年至2019年自由软件基金会。 此文件是GNUC库的一部分。 GNUC库是自由软件;您可以重新分发它和/或 根据GNU小公众的条款对其进行修改 自由软件基金会发布的许可证;任何一个 许可证的2.1版,或(由您选择)任何更高版本。 分发GNU C库是希望它会有用, 但无任何保证;甚至没有任何关于 适销性或适合某一特定目的。见GNU 有关更多详细信息,请参阅较低的通用公共许可证。 您应该已经收到GNU Lesser General Public的副本 许可证以及GNUC库;如果没有,请参阅 . 作为特殊例外,如果将此文件中的代码链接到 使用GNU编译器编译以生成可执行文件的文件, 这不会导致生成的可执行文件被 GNU较小的通用公共许可证。这一例外并不存在 但是,要使可执行文件无效的任何其他原因 可能包含在GNU较小的通用公共许可证中。 此例外情况适用于其版权所有者发布的代码 在包含异常的文件中*/ #包括“libioP.h” #包括“stdio.h” #未定义 int _IO_getc(文件*fp) { int结果; 检查_文件(fp、EOF); 如果(!\u IO\u需要锁定(fp)) 返回已解锁(fp); _IO_获取_锁(fp); 结果=_IO_getc_解锁(fp); _IO_释放_锁定(fp); 返回结果; } #未定义getc 弱别名(_IO_getc,getc) 弱别名(_IO_getc、fgetc) #如果没有 #undef getc_解锁 弱别名(_IO_getc,getc_解锁) 弱别名(\u IO\u getc、fgetc\u解锁) #恩迪夫
选择一个LandUAGE如果它不是以#define开头,那么它可能不是宏。你能发布你正在查看的代码并告诉我们它来自哪个库吗?不同的系统和编译器将使用不同的实现。抱歉,我说的是fgetc和getc之间的C
,第一个是函数,第二个是宏
不,
getc
可能是宏。“我们知道fgetc和getc之间的区别是,第一个是函数,第二个是宏。”。不,我们不知道。不要求
getc
是宏。如果你指的是一个例子,它说:可以作为一个宏程序来实现,除非它有副作用,否则是不允许的。当然,如果真的很慢,你可能会想重新考虑你的方法,但这是合法的。