这里的'L'有什么意义?

3
//Using the if-else
#include <iostream>
using std::cin;
using std::cout;
using std::endl;

int main() {
  long number = 0;                  // Store input here
  cout << "Enter an integer less than 2 billion: ";
  cin >> number;
  cout << endl;

  if(number % 2L == 0)              // Test remainder after division by 2
    cout << "Your number is even."  // Here if remainder is 0
         << endl;
  else
    cout << "Your number is odd."   // Here if remainder is 1
         << endl;
  return 0;
}

在第一个“if”条件中,为什么他们在2后面加上了“L”?去掉'L'似乎也可以正常运行代码。


2
这里不需要它。 - Oliver Charlesworth
L是做什么的?我以后会需要它吗? - user2826094
它仅适用于“long”字面量。 - Jamal
L 去掉,尝试输入一个非常大的数字。那么你将会除以一个 int 类型的数。这可能会引起问题。 - nhgrif
2L 是一个长整型字面值。单独的 2 是一个整型字面值。由于变量是长整型,2 也将被提升为长整型,因此代码在有或无 L 的情况下是等价的。 - pburka
2
@nhgrif 不是的。整数字面值不一定是 int,它们至少是 int(如果 int 不够,则为 long int)。 - dyp
2个回答

11
L后缀用于表示数字字面量的类型为long int。如果只是将值分配给变量,则通常不需要,因为根据C++11 §2.14.2 ¶2(特别是表6),没有后缀的十进制整数字面量将是可以表示它的第一个类型之一,包括 intlong int 或者 long long int1 所以,您不会冒着被截断的风险。但是:
1.您对文字的类型有一定程度的不确定性(例如,32768 可能是intlong,这取决于平台/编译器);
2.您可能无意中获得错误类型的文字,而导致表达式出错。
因此,在想要确保文字类型为long(或更大)的情况下,请在上下文中指定L,其中需要注意两个重要情况:
  • resolving overloads; if you have two overloads of a function, one for int and one for long, and you want to be sure to call the long one even if you are passing a small number, you'll have to use a long literal;

    void foo(int);
    void foo(long);
    
    foo(1);      // <-- will call the first overload
    foo(1L);     // <-- will call the second overload
    foo(32768);  // <-- may call the first or the second overload, depending
                 //     from the specific platform
    foo(32768L); // <-- will call the second overload
    
  • but most importantly: avoid surprises when doing arithmetic; if you perform e.g. a multiplication like this:

    int a;
    ...
    long v=32767*a; // don't let the "long" fool you - 32767*a is evaluated as an int!
    

    32767 is an int literal (since it's small enough to fit an int), a is an int, and the result will be an int, even if you are assigning to a long. This may be a problem if a can be big enough to overflow your calculation; by specifying a long literal, you guarantee that you'll perform a long multiplication.

    long v=32767L*a; // now we are doing all the math with longs
    

    (This problem is actually way more frequent with division and FP literals, where often you have to specify double or float literals to get the intended "real division" behavior)

    As @chris suggests, a way more frequent situation (of this same kind) arises when doing "big" bitshifts, e.g.:

    long long mask=1<<53;
    

    presents the same problem as above: 1 is an int, 53 is an int, the computation will be performed with ints, resulting in overflow (although in this particular case any decent compiler will issue a warning); here the correct form would be:

    long long mask=1LL<<53; // LL is the suffix for long long
    

针对你的代码,去掉L不会有任何风险;因为number已经是long类型了,在执行模运算时,2也会被转换成long类型(根据“通常算术转换”的规则,§5 ¶10和§4.5),所以这里L没有任何影响。

尽管如此,在许多情况下,保留“期望类型”的字面量也不失为一个好主意:它保证了即使其他操作数的类型由于某种原因变为了更窄的类型,计算仍将按照预期的方式进行(虽然在模运算中这并不会有任何区别)。


  1. 整型字面量的类型是表6中对应列表中第一个可以表示其值的类型。 来自C++11标准的表格,描述用于整型字面量的类型


我发现这种情况通常发生在类似 1 << 53 的东西上。 - chris
@chris:是的,那个问题也困扰了我好几次;我会把它加到答案里。 - Matteo Italia
至少编译器(GCC)在这方面做得很好,会发出警告。 - chris

0

在这种情况下,它是不必要的。

L 表示长整型,这意味着它会保留更多的空间,以便你的计算超出了普通整数的范围。


L与变量无关,而与字面量有关。如果您将结果分配给变量,则其大小将根据其类型确定,您分配给它的内容不会有任何影响(除非我们谈论的是“auto”变量的初始化)。 - Matteo Italia
@MatteoItalia:无论是否被赋值,它仍然是存储在内存中用于计算的变量。如果不这样做,在将其存储到赋值之前,可能会损坏您的计算。 - Wolph
不,字面值并不是变量,它是一种基本表达式,在大多数表达式中,它将仅保留在寄存器中或作为生成的汇编中的立即值。当然,使用错误类型的字面值可能会破坏您的计算,但这与“内存中保留的空间”无关,而与类型信息告诉编译器如何执行计算有关。 - Matteo Italia
你是否否认 int 类型与 long long int 类型在内存中的占用不同?如果不是,那么我不明白它如何与“内存中的保留空间”无关,这不是唯一的区别,但绝对是相关的。 - Wolph
不,我的意思是在简单表达式的上下文中(就像原帖中的那个),这几乎是无关紧要的,因为字面值几乎肯定嵌入到生成的汇编代码中作为立即值。此外,这样简单的计算可能会在CPU寄存器中完成,也许只有在将其存储到变量中时才会访问内存,在这种情况下,使用的存储空间取决于目标变量的类型,而不是表达式的类型。再次强调:获取字面值的类型是为了让编译器生成正确的代码,使用的空间(如果有)是一个副作用。 - Matteo Italia
如果在32位CPU(或32位模式)上超过32位,它将溢出寄存器。因此,无论是否影响内存,它仍然非常相关。 - Wolph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接