接受int参数是否需要%c fprintf说明符
在C99标准第7.19.6.1节第8段中:接受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
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? */
变量和literalint
常量是否是使用int
说明符将值传递给%c
的唯一安全方法fprintf
%cfprintf
的转换规范需要一个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')是的,我忘了字符常量是C中的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);