Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.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
接受int参数是否需要%c fprintf说明符_C_C99_Language Lawyer_Printf_Variadic Functions - Fatal编程技术网

接受int参数是否需要%c fprintf说明符

接受int参数是否需要%c fprintf说明符,c,c99,language-lawyer,printf,variadic-functions,C,C99,Language Lawyer,Printf,Variadic Functions,在C99标准第7.19.6.1节第8段中: c如果不存在l长度修饰符,则将int参数转换为 无符号字符,并写入结果字符 在C99标准第7.19.6.1节第9段中: 如果任何参数不是相应转换规范的正确类型,则行为未定义 fprintf函数是否需要int参数 例如,传递一个无符号int是否会导致未定义的行为: unsigned int foo = 42; fprintf(fp, "%c\n", foo); /* undefined behavior? */ 这让我担心,因为一个实现可以将ch

在C99标准第7.19.6.1节第8段中:

c
如果不存在
l
长度修饰符,则将
int
参数转换为
无符号字符
,并写入结果字符

在C99标准第7.19.6.1节第9段中:

如果任何参数不是相应转换规范的正确类型,则行为未定义

  • fprintf
    函数是否需要
    int
    参数
例如,传递一个
无符号int
是否会导致未定义的行为:

unsigned int foo = 42;

fprintf(fp, "%c\n", foo); /* undefined behavior? */
这让我担心,因为一个实现可以将
char
定义为具有与
无符号char
相同的行为(第6.2.5节第15段)

在这些情况下,整数提升可能会指示
char
为空。因此,让以下代码在这些实现上冒着未定义行为的风险:

char bar = 'B';

fprintf(fp, "%c\n", bar); /* possible undefined behavior? */
  • int
    变量和literal
    int
    常量是否是使用
    %c
    说明符将值传递给
    fprintf
    的唯一安全方法

  • %c
    fprintf
    的转换规范需要一个
    int
    参数。默认参数后的值必须是
    int
    类型

    未定义的行为:
    foo
    必须是
    int

    char bar = 'B';
    fprintf(fp, "%c\n", bar);
    
    非未定义行为:
    bar
    被提升(默认参数提升)为
    int
    ,因为
    fprintf
    是一个可变函数


    编辑:公平地说,仍然有一些非常罕见的实现可以是未定义的行为。例如,如果
    char
    是一种无符号类型,且并非所有
    char
    值都可以在
    int
    中表示(如中),则默认参数升级为
    unsigned int

    是,
    printf
    with
    %c
    或多或少需要
    int
    参数

    char bar = 'B';
    fprintf(fp, "%c\n", bar);
    
    如果参数的类型小于
    int
    ,则将提升该参数。在大多数情况下,升级到
    int
    ,行为定义明确。在非常罕见的情况下,
    char
    是无符号的,
    sizeof(int)==1
    (这意味着
    char\u BIT>=16
    ),一个
    char
    参数被提升为
    unsigned int
    ,这可能导致未定义的行为

    字符常量的类型已经是
    int
    ,因此
    printf(“%c”,“x”)
    即使在外来系统上也定义得很好。(在C++中,字符常量属于类型<代码> char ) 这:

    严格地说,它有未定义的行为。7.1.4p1表示:

    如果函数的参数具有。。。a类型(升级后)不可用 对于参数数目可变的函数,行为 没有定义

    fprintf
    调用显然与此相冲突。(感谢ouah指出这一点。)

    另一方面,6.2.5p6表示:

    对于每个有符号整数类型,都有一个对应的 不同)无符号整数类型(用关键字指定 未签名的),它使用相同的存储量(包括符号信息)并具有相同的对齐要求

    第6.2.5p9节规定:

    有符号整数类型的非负值范围是一个子范围 对应的无符号整数类型的 每种类型中的相同值都是相同的

    加上脚注:

    相同的表示和对齐要求意味着 作为函数参数的互换性,从 职能和工会成员

    脚注指出,
    int
    unsigned int
    类型的函数参数可以互换,只要值在这两种类型的可表示范围内。(对于典型的32位系统,这意味着值必须在0到231-1的范围内;
    int
    值从-231到-1,以及
    无符号int
    值从231到232-1,不在其他类型的范围内,并且不可互换。)

    但C标准中的脚注是非规范性的。它们通常旨在澄清规范性文本中规定的要求,而不是强加新的要求。但是这里的规范性文本仅仅说明了相应的有符号和无符号类型具有相同的表示形式,这并不一定意味着它们的传递方式与函数参数相同。原则上,编译器可以忽略该脚注,例如,在不同寄存器中传递
    int
    无符号int
    参数,使
    fprintf(fp,“%c\n”,foo)未定义

    但是在实践中,实现没有理由玩这种游戏,您可以依赖于
    fprintf(fp,“%c\n”,foo)以按预期工作。我从来没有见过或听说过一个无法工作的实现

    就我个人而言,我宁愿不依赖这一点。如果我在写代码,我会通过cast添加一个显式转换,这样这些问题就不会首先出现:

    unsigned int foo = 42;
    fprintf(fp, "%c\n", (int)foo);
    

    或者我会首先将
    foo
    设为
    int

    你可以一直编写
    fprintf(fp,%c\n,'B')int
    类型,不是吗?我想OP特别担心
    char
    无符号和
    int
    一样宽,在这种情况下,
    bar
    被提升为
    unsigned int
    。@ouah不会对
    char
    中的
    fall进行默认参数提升,而是对第6.5.2.2节第6段中的每个参数
    类别执行整数提升?我很好奇
    unsigned int foo = 42;
    fprintf(fp, "%c\n", (int)foo);