C标准库的可扩展性对C++程序的影响有多大

How much does the C standard library extensibility affect C++ programs?

本文关键字:影响 程序 标准 可扩展性 C++      更新时间:2023-10-16

取此代码:

int issuecode(int i)
{
  return 2 * i;
}
int main(int argc, char **argv)
{
  return issuecode(argc);
}

按照我的理解,如果编译成C程序,它将有未定义的行为。我根据这些标准报价进行推理:

C99,7.26(或C11,7.31)

为了方便起见,以下名称被分组在单独的标题下。下面描述的所有外部名称都是保留的,无论程序包含什么标头。

C99,7.26.2(或C11,7.31.2)

isto开头的函数名以及小写字母可以添加到<ctype.h>标头中的声明中。

C99,7.1.3(或C11,7.1.3)

  1. 每个标头声明或定义其关联子条款中列出的所有标识符,并可选地声明或定义在其关联的未来库方向子条款中列示的标识符以及始终保留用于任何用途或用作文件范围标识符的标识符。

    […]

    • 以下任何子条款中的所有具有外部链接的标识符(包括未来的库方向)始终保留为用作具有外部连接的标识符
  2. […]如果程序在保留标识符的上下文中声明或定义标识符(7.1.4允许的除外),或将保留标识符定义为宏名称,则行为未定义。

基于以上,我相信函数名issuecode实际上是为在<ctype.h>中使用而保留的,因此该程序在技术上具有UB。

问题0(健全性检查):我对标准的理解是否正确,程序的行为在技术上是否未定义?

问题1:如果编译为C++代码,程序会有UB吗?

我相信答案是"不",因为从下面的引文中,我想说C的"未来库方向"不是C++标准库的一部分,但我真的不确定。

C++11,21.7

  1. 表74、75、76、77、78和79分别描述了标题<cctype><cwctype><cstring><cwchar><cstdlib>(字符转换)和<cuchar>

  2. 这些标头的内容应分别与标准C库标头<ctype.h><wctype.h><string.h><wchar.h><stdlib.h>以及C Unicode TR标头相同,但有以下修改:

"以下修改"均未提及额外的保留标识符。表74是类似isdigitisalnum的函数名称的免税列表。

C++11,C.2

1.本小节总结了标准C库中包含的C++标准库的内容。它还总结了其他子条款(17.6.1.2、18.2、21.7)中提到的标准C库中定义、声明或行为的明确变化

7.C++标准库提供了来自C库的209个标准函数,如表153所示。

同样,表153是一个纳税清单。

问题2:假设我在问题1上错了,并且程序实际上在C++中也有UB,下面的更改会影响这一点吗?

namespace foo {
  int issuecode(int i)
  {
    return 2 * i;
  }
}
using namespace foo;
int main(int argc, char **argv)
{
  return issuecode(argc);
}

注意:标准引号取自草案N1256(C99)、N1570(C11)和N3242(C++11),它们是各自语言版本的最新公开草案。

为了方便起见,以下名称被分组在单独的标题下。下面描述的所有外部名称都是保留的,无论程序包含什么标头。

有一个预定义的保留函数列表,如果您的函数在名称上没有冲突,就没有问题。

以is或to开头的函数名,以及小写字母可以添加到<ctype.h>头球

存在的操作术语可以添加到<ctype.h>标头中。"is or to"只是对申报组织的指导。

所以那里从来没有真正的不明确的行为。。。

至于C++,我认为这遵循了同样的想法——举个例子:

namespace foo{
  int isupper ( int c );
}
#include <cctype>
using namespace foo;
int main(void){
    isupper(92);
}

这应该会产生编译器错误,因为您的函数与C函数在名称上发生冲突,但由于名称空间的原因,可以通过在调用的开头添加std::foo::来很容易地解决这一问题。

C++11 17.6.1.2标头

172)C标准库头(附录D.5)也定义了全局名称空间内的名称,而C的C++头库设施(17.6.1.2)也可以在全局命名空间中定义名称。

然而,在C++标准库中在C中定义为宏的名称)在命名空间std的命名空间范围(3.3.6)内未指定是否首先在全局命名空间范围内声明这些名称,然后注入通过显式使用声明(7.3.3)将其转换为命名空间std。

因此,如果不包括<cctype>,则行为定义良好。如果您这样做,则未指明。