Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对函数使用宏重写_C++_C_C Libraries - Fatal编程技术网

C++ 对函数使用宏重写

C++ 对函数使用宏重写,c++,c,c-libraries,C++,C,C Libraries,我在阅读C库中header的实现时,遇到了函数的宏重写以及函数声明。我想知道这有什么用。无论是使用宏还是函数,都需要重写什么 编辑: 例如: *更不用说函数定义在单独的文件中没有理由使用宏而不是函数。在过去,可能会提高效率,但现代编译器完全能够在适当的地方内联函数调用 您必须给出一个宏覆盖的示例。具有相同名称的函数声明和宏声明不能合理共存。例如,一旦定义了宏,就很难调用函数,您必须先取消定义宏。完全没有理由使用宏而不是函数。在过去,可能会提高效率,但现代编译器完全能够在适当的地方内联函数调用 您

我在阅读C库中header的实现时,遇到了函数的宏重写以及函数声明。我想知道这有什么用。无论是使用宏还是函数,都需要重写什么

编辑: 例如:


*更不用说函数定义在单独的文件中

没有理由使用宏而不是函数。在过去,可能会提高效率,但现代编译器完全能够在适当的地方内联函数调用


您必须给出一个宏覆盖的示例。具有相同名称的函数声明和宏声明不能合理共存。例如,一旦定义了宏,就很难调用函数,您必须先取消定义宏。

完全没有理由使用宏而不是函数。在过去,可能会提高效率,但现代编译器完全能够在适当的地方内联函数调用


您必须给出一个宏覆盖的示例。具有相同名称的函数声明和宏声明不能合理共存。例如,一旦定义了宏,就很难调用函数,您必须先取消定义宏。

实际的接口是三个数组,例如,\u Ctype数组返回字符的类型。宏,例如,是。。。宏用于方便使用_Ctype数组

我认为数组是固定的,宏可以根据您的用例进行调整。您可以编写新宏,更改现有宏。或者完全忽略宏


这里的方法是为了速度和兼容性。使用现代C++结构,人们会用不同的方式编写这样的接口。

< P>实际的接口是三个数组,例如,ycType数组返回字符的类型。宏,例如,是。。。宏用于方便使用_Ctype数组

我认为数组是固定的,宏可以根据您的用例进行调整。您可以编写新宏,更改现有宏。或者完全忽略宏


这里的方法是为了速度和兼容性。使用现代C++结构,人们会用不同的方式编写这样的接口。

< P>标准要求它所指定的函数必须定义为函数,并且必须在适当的标头中声明,以便可以将指针传递给函数。 C标准允许类似于宏的函数重写函数

该标准有一个坚实的规则块,我已将其重新格式化为项目符号列表。前两个要点与问题没有直接关系

^1除非以下详细说明中另有明确说明,否则以下各项均适用:

如果函数的参数具有无效值,例如函数域之外的值、程序地址空间之外的指针或空指针,或指向不可修改存储的指针。如果相应的参数不是const限定的,或者具有可变参数数的函数不期望升级后的类型,则行为未定义。 如果函数参数被描述为数组,则实际传递给函数的指针应具有一个值,使得如果指针指向该数组的第一个元素,则所有有效的地址计算和对对象的访问实际上都是有效的。 头中声明的任何函数都可以作为头中定义的类似于宏的函数来实现,因此,如果在包含库函数的头时显式声明库函数,则可以使用以下技术之一确保声明不受此类宏的影响。 函数的任何宏定义都可以通过将函数名括在括号中来局部抑制,因为该名称后面没有表示宏函数名扩展的左括号。出于同样的语法原因,即使库函数也被定义为宏,也允许使用库函数的地址。185 使用undef删除任何宏定义也将确保引用实际函数。 对作为宏实现的库函数的任何调用都应扩展为只对其每个参数求值一次的代码,必要时用括号完全保护,因此通常可以安全地使用任意表达式作为参数。186 同样,下列子条款中描述的类似于宏的函数可以在表达式中调用,只要可以调用具有兼容返回类型的函数。187 所有列为扩展为整数常量表达式的类对象宏还应适用于if预处理指令。 ^2前提是库函数可以 eclared不引用头中定义的任何类型,也允许在不包含其关联头的情况下声明函数并使用它

185这意味着一个实现应该为每个库函数提供一个实际函数,即使它也为该函数提供一个宏

186此类宏可能不包含相应函数调用所包含的序列点

187由于保留了外部标识符和一些以下划线开头的宏名称,因此实现可能会为这些名称提供特殊的语义。例如,标识符_BUILTIN_abs可用于指示生成abs功能的内嵌代码。因此,适当的头可以指定

     #define abs(x) _BUILTIN_abs(x)
对于其代码生成器将接受它的编译器。以这种方式,希望保证诸如abs之类的给定库函数将是真实函数的用户可以编写

     #undef abs
实现的头是提供abs的宏实现还是内置实现。该函数的原型位于任何宏定义之前,并且被任何宏定义隐藏,因此也被揭示出来

问题中的标题说明了保留标识符的使用§7.1.3保留标识符]。它声明头指定要声明的函数。它提供了重写这些函数的宏,相信使用这些函数比调用实现数组访问的函数更快

通过这种方式实现后,如果需要将指向某个分类或转换函数的指针传递给其他代码,则可以这样做。如果只提供了宏,那么您就必须使用一些特技才能将实际函数作为指针传递

该标准仔细地规定了一些宏确实必须是宏——offsetof和va_start和va_arg是我想到的三个宏。但是标准中的绝大多数函数必须作为函数实现——但是如果实现者认为这是合适的话,可以被宏覆盖

宏功能类似于宏的要求也很重要。它允许使用名称,而不必在后面加括号来获取指向函数的指针。如果宏的功能与头中包含的类似于define isupper(而不是define isupperc)isupperc(而不是define isupperc)的内容不同,那么就不可能依赖于访问标准函数名¨2规则允许您在不包含以下内容的情况下写入代码:


您将保证库中有一个函数isupper与期望值相匹配,即使还有一个_isupper函数。

C标准要求它指定的函数必须定义为函数,并且必须在适当的标题中声明,这样就可以传递指向函数的指针

C标准允许类似于宏的函数重写函数

该标准有一个坚实的规则块,我已将其重新格式化为项目符号列表。前两个要点与问题没有直接关系

^1除非以下详细说明中另有明确说明,否则以下各项均适用:

如果函数的参数具有无效值,例如函数域之外的值、程序地址空间之外的指针或空指针,或指向不可修改存储的指针。如果相应的参数不是const限定的,或者具有可变参数数的函数不期望升级后的类型,则行为未定义。 如果函数参数被描述为数组,则实际传递给函数的指针应具有一个值,使得如果指针指向该数组的第一个元素,则所有有效的地址计算和对对象的访问实际上都是有效的。 头中声明的任何函数都可以作为头中定义的类似于宏的函数来实现,因此,如果在包含库函数的头时显式声明库函数,则可以使用以下技术之一确保声明不受此类宏的影响。 函数的任何宏定义都可以通过将函数名括在括号中来局部抑制,因为该名称后面没有表示宏函数名扩展的左括号。出于同样的语法原因,即使库函数也被定义为宏,也允许使用库函数的地址。185 使用undef删除任何宏定义也将确保引用实际函数。 对作为宏实现的库函数的任何调用都应扩展为只对其每个参数求值一次的代码,必要时用括号完全保护,因此通常可以安全地使用任意表达式作为参数。186 同样,这些功能类似于ma 可以在表达式中调用具有兼容返回类型的函数的任何位置调用以下子条款中描述的CRO。187 所有列为扩展为整数常量表达式的类对象宏还应适用于if预处理指令。 ^2如果库函数可以在不引用头中定义的任何类型的情况下声明,也可以在不包含其关联头的情况下声明和使用该函数

185这意味着一个实现应该为每个库函数提供一个实际函数,即使它也为该函数提供一个宏

186此类宏可能不包含相应函数调用所包含的序列点

187由于保留了外部标识符和一些以下划线开头的宏名称,因此实现可能会为这些名称提供特殊的语义。例如,标识符_BUILTIN_abs可用于指示生成abs功能的内嵌代码。因此,适当的头可以指定

     #define abs(x) _BUILTIN_abs(x)
对于其代码生成器将接受它的编译器。以这种方式,希望保证诸如abs之类的给定库函数将是真实函数的用户可以编写

     #undef abs
实现的头是提供abs的宏实现还是内置实现。该函数的原型位于任何宏定义之前,并且被任何宏定义隐藏,因此也被揭示出来

问题中的标题说明了保留标识符的使用§7.1.3保留标识符]。它声明头指定要声明的函数。它提供了重写这些函数的宏,相信使用这些函数比调用实现数组访问的函数更快

通过这种方式实现后,如果需要将指向某个分类或转换函数的指针传递给其他代码,则可以这样做。如果只提供了宏,那么您就必须使用一些特技才能将实际函数作为指针传递

该标准仔细地规定了一些宏确实必须是宏——offsetof和va_start和va_arg是我想到的三个宏。但是标准中的绝大多数函数必须作为函数实现——但是如果实现者认为这是合适的话,可以被宏覆盖

宏功能类似于宏的要求也很重要。它允许使用名称,而不必在后面加括号来获取指向函数的指针。如果宏的功能与头中包含的类似于define isupper(而不是define isupperc)isupperc(而不是define isupperc)的内容不同,那么就不可能依赖于访问标准函数名¨2规则允许您在不包含以下内容的情况下写入代码:


即使还有一个_isupper函数,您也可以保证库中有一个函数isupper与期望值相匹配。

显示一个您所引用的示例。@kaylum我编辑了一个示例define 0x200是一个语法错误,我怀疑它应该是define _xa0x200。但是,对于你的问题,这不是很重要。请决定你是否想要关于C或C++的答案。大多数情况下,答案是不同的,因为语言也大不相同。请给出一个您所指内容的示例。@kaylum我编辑了一个示例define 0x200是一个语法错误,我怀疑它应该是define _XA0x200。但是,对于你的问题,这不是很重要。请决定你是否想回答C或C++,通常答案是不同的,因为语言也有很大的不同。我相信C++中的α是一个函数,但我可能错了。不知道C标准是怎么说的。它们绝对可以共存,而且使用函数不必取消宏定义。isalphach调用该函数。这是因为像宏这样的函数的调用必须是宏的名称,后跟可选的空格和一个空格。当名称在括号中时,后面跟着一个,因此它不是宏调用。@PeteBecker有趣的是,幸运的是我很少再使用宏了。如果你想使用函数,我想你可以编写undef isalpha。我相信C++中的α是一个函数,但我可能错了。不知道C标准是怎么说的。它们绝对可以共存,而且使用函数不必取消宏定义。isalphach调用该函数。这是因为像宏这样的函数的调用必须是宏的名称,后跟可选的空格和一个空格。当名称在括号中时,后面跟着一个,因此它不是一个宏调用。@PeteBecker有趣的是,幸运的是我很少再使用宏了\u Ctype不是一个函数,它是一个用于 查找设置了位以指示字符类的值_Tolower和_Toupper也只是数组。_Ctype不是函数,它是一个数组,用于查找设置了位以指示字符类的值_Tolower和_Toupper也只是数组。