代码之家  ›  专栏  ›  技术社区  ›  SF.

printf(“…%c…”,'\0')和家庭-会发生什么?

  •  2
  • SF.  · 技术社区  · 14 年前

    采用printf格式字符串的各种函数在遇到 %c 格式给定值 \0 / NULL ? 他们应该怎么做?安全吗?它是定义的吗?它是特定于编译器的吗?

    例如 sprintf() -它是否将结果字符串裁剪为空?它会返回多长时间?

    威尔 printf() 输出整个格式字符串还是只输出到新的空值?

    威尔 va_args + vsprintf / vprintf 不知何故受到影响?如果是这样,怎么办?

    如果在std::str in g.c_str()中的某个点上执行此空值,是否存在内存泄漏或其他问题的风险?

    避免这种警告的最佳方法是什么(消毒输入?)

    3 回复  |  直到 14 年前
        1
  •  3
  •   Clifford    10 年前

    当您输出一个nul时会发生什么取决于输出设备。

    它是非打印字符,即 isprint('\0') == 0 ;所以当输出到显示设备时,它没有可见的影响。但是,如果重定向到文件(或者如果调用 fprintf() ,它将在文件中插入一个nul(零字节);其含义将取决于文件的使用方式。

    当输出到C字符串时,它将被标准字符串处理函数解释为字符串终止符,尽管任何其他随后的格式说明符仍将导致数据放在nul之后的缓冲区中,而nul对于标准字符串处理函数是不可见的。如果数组最终不被解释为C字符串,这仍然有用。

    如果在std::str in g.c_str()中的某个点上执行此空值,是否存在内存泄漏或其他问题的风险?

    这完全不清楚您所说的是什么意思,但是如果您建议使用返回的指针 std::string.c_str() 作为缓冲 sprintf() 不要! c_str() 返回A const char* ,通过此类指针修改字符串是未定义的。然而,这是一个不同的问题,与向字符串中插入nul完全无关。

    避免这种警告的最佳方法是什么(消毒输入?)

    我正在努力想一种情况,在这种情况下,您可能会“意外”地编写这样的代码,那么为什么您需要防范它呢?你有什么特别的情况吗?尽管我觉得这是不可信的,而且可能是不必要的,但最困难的是:

    if( c != 0 )
    {
        printf( "%c", c ) ;
    }
    

    或者更有用(因为您可能希望在输出中避免使用其他字符)

    if( isgraph(c) || isspace(c) )
    {
        printf( "%c", c ) ;
    }
    

    只输出可见字符和空白(空格, '\t' , '\f' , '\v' , '\n' , '\r' )

    注意,你也可以考虑 isprint() 而不是 isgraph(c) || isspace(c) 但不包括 “t” , “F” , “V” , “n” “R”

        2
  •  8
  •   Clifford    14 年前

    任何采用标准C字符串的函数都将在第一个空值处停止,不管它是如何到达那里的。

    当您使用格式中的%c并使用0作为字符值时,它将在输出中插入一个空值。 printf 将输出空值作为输出的一部分。 sprintf 还将向结果字符串中插入空值,但当您将输出传递给另一个函数时,该字符串似乎将在该点结束。

    一个std::string在其内容中的任何地方都可以包含一个空值,但是当您使用c_str方法将其传递给函数时,请参见上面的答案。

        3
  •  3
  •   caf    14 年前

    printf() sprintf() 将继续通过 '\0' 字符插入方式 %c ,因为它们的输出是根据格式字符串的内容定义的,并且 %C 不表示格式字符串的结尾。

    这包括它们的计数;因此:

    sprintf(x, "A%cB", '\0')
    

    必须始终返回3(尽管 strlen(x) 之后将返回1)。