C如何处理char sums?

时间:2015-05-04 16:53:12

标签: c++ c char int

当我在C ++中时,我调用了一个重载函数foo,如下所示:

foo('e' - (char) 5)

它可以输出"这是一个字符#34;或者"这是一个int"根据类型结果。我得到了#34;这是一个int"从我的程序,像这样:

#include <iostream>

void foo(char x)
{
    std::cout << "output is a char" << std::endl;
}
void foo(int x)
{
    std::cout << "output is an int" << std::endl;
}
int main()
{
    foo('a' + (char) 5);
}

我的导师说在C中,上面的表达式('a' + (char) 5)计算为char。我在C99标准中看到,字符被提升为整数以查找总和,但是当它完成时C是否会将它们重新转换为字符?我无法找到任何看似可信的参考文献,说明促销完成后C实际做了什么,并找到了总和。

总和是作为int保留还是作为char给出?我如何在C中证明这一点,或者是否有我不理解/发现的参考?

7 个答案:

答案 0 :(得分:6)

从C标准,6.3.1.8通常的算术转换,强调我的:

  

许多期望算术类型操作数的运算符会导致转换并产生结果   以类似的方式输入类型。目的是确定操作数的通用实数类型   和结果。对于指定的操作数,将转换每个操作数,而不更改类型   域,对应的实类型是常见的实类型。的除非   另外明确说明,常见的真实类型也是相应的实际类型   结果,其类型域是操作数的类型域,如果它们相同,   否则复杂。此模式称为通常的算术转换

     
      
  • 首先,如果任一操作数的相对实数类型为long double ...
  •   
  • 否则,如果任一操作数的相应实数类型为double ...
  •   
  • 否则,如果任一操作数的相应实数类型为float ...
  •   
  • 否则,对两个操作数执行整数提升。然后将以下规则应用于提升的操作数:   
        
    • 如果两个操作数具有相同的类型,则不需要进一步转换。
    •   
  •   

所以你完全正确。表达式'a' + (char) 5的类型为int。除非用户明确要求,否则不会重新发送回char。请注意,'a'此处的类型为int,因此它只是需要提升的(char)5。这在6.4.4.4字符常量中规定:

  

整数字符常量是包含的一个或多个多字节字符的序列   在单引号中,如'x'   ...
  整数字符常量的类型为int

有一个例子证明明确重铸为char

  

执行片段

char c1, c2;
/* ... */
c1 = c1 + c2
     

'整数促销''要求抽象机器将每个变量的值提升为int大小,然后添加两个int并截断总和。如果可以在没有溢出的情况下添加两个char,或者以静默方式溢出包装以产生正确的结果,则实际执行只需要产生相同的结果,可能省略促销。

此处的截断只会发生,因为我们会分配回char

答案 1 :(得分:3)

不,C不会将它们重新制作回字符。

标准(ISO / IEC 9899:1999)说(6.3.1.8常规算术转换):

  

许多期望算术类型操作数的运算符会导致转换并产生结果   以类似的方式输入类型。目的是确定操作数的通用实数类型   和结果。对于指定的操作数,将转换每个操作数,而不更改类型   域,对应的实类型是常见的实类型。的除非   另有明确说明,常见的实际类型也是相应的实际类型   结果,其类型域由运营商确定。

答案 2 :(得分:2)

你的导师似乎错了。除了你的标准发现算术提升到int之外,我们可以使用一个简单的测试程序来显示行为(当然没有标准证明,但与C ++测试的证明水平相同):

#include <stdio.h>

int main () {
   printf("%g",'c' - (char)5);
}

生成

  

警告:format指定类型'double'但参数的类型为'int'

this threadgcc

答案 3 :(得分:0)

它被提升为int,没有什么可以告诉编译器它应该使用其他任何东西。你可以转换回这样的字符:

foo((char)('a' + 5));

这告诉编译器将计算结果视为char,否则将其保留为int

答案 4 :(得分:0)

来自C ++标准(C ++ Working Draft N3797,5.7 Additive operators)

  

1添加剂操作符+和 - 从左到右组。 通常   对算术或算术的操作数执行算术转换   枚举类型。

和(5个表达式)

  

10许多期望算术或算术操作数的二元运算符   枚举类型导致转换并产生类似的结果类型   办法。目的是产生一种普通类型,它也是一种类型   结果。这种模式称为通常的算术转换,   其定义如下:

     

...

     

- 否则,应执行整体促销(4.5)   两个操作数 .62然后以下规则应适用于   推广操作数:

因此函数调用中的表达式

foo('a' + (char) 5);

的类型为int。 要使用char类型的参数调用重载函数,您必须编写例如

foo( char( 'a' + 5 ) );

foo( ( char )( 'a' + 5 ) );

或者您可以像

一样使用C ++强制转换
foo( static_cast<char>( 'a' + 5 ) );

C ++标准的上述引用也适用于C标准。可见的区别在于,在C ++中,字符文字的类型为char,而在C中,它们的类型为int

所以在C ++中声明的输出

std::cout << sizeof( 'a' ) << std::endl;

将等于1.

在C语句中输出语句

printf( "%zu\n", sizeof( 'a' ) );

将等于sizeof( int ),通常等于4。

答案 5 :(得分:0)

第6.5.2.2/6节

  

如果表示被调用函数的表达式具有类型   不包括原型,执行整数促销   每个论点......

所以问题的答案取决于函数原型。如果函数声明为

void foo(int x)

void foo()

然后函数参数将作为int传递。

OTOH,如果函数声明为

void foo( char x )

然后表达式的结果将隐式转换为char

答案 6 :(得分:0)

在C中(与C ++不同),字符文字'a'的类型为int(§6.4.4.4¶10:“整数字符常量的类型为int。”)

即使不是这种情况,C标准也明确规定在评估运算符+之前,“[i]两个操作数都有算术类型,对它们执行通常的算术转换。 “ (C11,§6.5.6¶4)在这方面,C和C ++具有相同的语义。 (参见C ++的[expr.add]§5.7¶1)