在strtol等人的规范中混淆了语言

时间:2011-07-14 23:17:12

标签: c standards-compliance language-lawyer strtol

strtol的规范在概念上将输入字符串分为“初始空格”,“主题序列”和“最终字符串”,并将“主题序列”定义为:

  

输入字符串的最长初始子序列,从第一个具有预期形式的非空白字符开始。如果输入字符串为空或完全由空格字符组成,或者第一个非空白字符不是符号或允许的字母或数字,则主题序列不应包含任何字符。

有一次,我认为“最长的初始子序列”业务类似于scanf的工作方式,"0x@"将扫描为"0x",匹配失败,然后是{{ 1}}作为下一个未读的角色。但是,在经过一些讨论后,我基本上确信"@"处理了预期形式的最长初始子序列,而不是最长的初始字符串,它是预期形式的某些可能字符串的初始子序列。

令我困惑的是规范中的这种语言:

  

如果主题序列为空或者没有预期的形式,则不进行转换; str的值存储在endptr指向的对象中,前提是endptr不是空指针。

如果我们接受似乎是“主题序列”的正确定义,那么就没有不具有预期形式的非空主题序列,而是(以避免冗余和混淆)文本应该只读:

  

如果主题序列为空,则不执行转换; str的值存储在endptr指向的对象中,前提是endptr不是空指针。

有人可以为我澄清这些问题吗?也许与过去的讨论或任何相关缺陷报告的链接将是有用的。

4 个答案:

答案 0 :(得分:3)

我认为C99语言很清楚:

  

主题序列被定义为最长的初始子序列   输入字符串,从第一个非空白字符开始,   这是预期的形式。

鉴于"0x@""0x@"不符合预期格式; "0x"不符合预期的格式;因此"0"是最长的初始子序列,具有预期的形式。

我同意这意味着您不能拥有非空的主题序列,而不是预期的形式 - 除非您解释以下内容:

  

"C"区域设置以外的其他区域设置主题   序列表格可以被接受。

...允许区域设置定义主题序列可能具有的其他可能形式,但仍然不是“预期形式”。

最后一段中的措辞似乎只是“带括号”。

答案 1 :(得分:2)

如果您从§7.20.1.4(strtol,strtoll,strtoul和strtoull函数)开始,可能更容易理解C99标准的¶2,而不是¶4:

  

¶2strtol,strtoll,strtoul和strtoull函数转换初始值   nptr指向long int的字符串部分,long long int,unsigned   long int和unsigned long long int表示。第一,   他们将输入字符串分解为三个部分:一个初始的,可能是空的序列   空白字符(由isspace函数指定),主题序列   类似于由base的值确定的某个基数表示的整数,和a   一个或多个无法识别的字符的最终字符串,包括终止null   输入字符串的字符。然后,他们尝试将主题序列转换为   整数,并返回结果。

     

¶3如果base的值为零,则主题序列的预期形式为a的预期形式   6.4.4.1中描述的整数常量,可选地前面带有加号或减号,但是   不包括整数后缀。如果base的值在2到36之间(包括),则   主题序列的预期形式是表示一个的字母和数字的序列   具有由base指定的基数的整数,可选地前面带有加号或减号,   但不包括整数后缀。来自(或A)到z(或Z)的字母是   归因于10到35的值;只有字母和数字的归属值较小   允许比基地的。如果base的值是16,则字符0x或0X可以   可选地在字母和数字序列之前,如果存在则在符号后面。

     

¶4主题序列被定义为输入字符串的最长初始子序列,...

特别是,¶3阐明了主题序列是什么。

答案 2 :(得分:1)

POSIX spec for strtol似乎更清晰:

  

这些函数应分别将str指向的字符串的初始部分转换为long和long long类型。首先,他们将输入字符串分解为三个部分:

     
      
  1. 一个初始的,可能是空的白色空格字符序列(由isspace()指定)

  2.   
  3. 主题序列被解释为以某个基数表示的整数,由基数值确定

  4.   
  5. 一个或多个无法识别的字符的最终字符串,包括输入字符串的终止NUL字符。

  6.         

    然后他们将尝试将主题序列转换为整数,并返回结果。

但当然,它不是规范性的,并且“遵循ISO C标准”。

答案 3 :(得分:1)