为什么在C中写入1000,000,000作为1000*1000*1000?

Spa*_*Dog 136 c integer objective-c literals

在Apple创建的代码中,有这一行:

CMTimeMakeWithSeconds( newDurationSeconds, 1000*1000*1000 )
Run Code Online (Sandbox Code Playgroud)

没有任何理由来表达1,000,000,0001000*1000*1000

为什么不1000^3呢?

Pio*_*ski 195

以乘法方式声明常量的一个原因是提高可读性,而运行时性能不受影响.此外,表明作者正在以数字的乘法方式思考.

考虑一下:

double memoryBytes = 1024 * 1024 * 1024;
Run Code Online (Sandbox Code Playgroud)

它显然比以下更好:

double memoryBytes = 1073741824;
Run Code Online (Sandbox Code Playgroud)

因为后者乍一看不是1024的第三个力量.

正如Amin Negm-Awad所提到的,^运算符是二进制的XOR.许多语言缺少内置的编译时取幂运算符,因此乘法.

  • 在具有取幂运算符的语言中,它不一定是'^'.例如,在Fortran中,它是'**'. (12认同)
  • 存储量为双倍?这似乎是潜在的错误来源. (12认同)
  • @supercat我知道这一点,但是通过使用double你可以有一个案例,比如说,你想要一部分内存范围,你除以`x`来得到子范围的大小......然后突然间你有一个小数字节,可能需要额外的逻辑来补偿. (7认同)
  • 您还应该在@chux中包含一个指向重要告诫的链接,如下面的答案所示:http://stackoverflow.com/a/40637622/1841533(特别是OP标记为"c",它非常容易受到影响'右手边操作似乎将所有术语限制为较小的类型,因此乘法可能会溢出'问题).https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow可能有助于避免那些人一般情况? (4认同)
  • 我们还应该注意,计算是在编译时完成的.C标准要求实现能够在编译时为语言的各种特性计算常量表达式,并且我们可以安全地假设在使用常量表达式时(如此示例中). (3认同)
  • 但请注意,“double storageBytes = 1024 * 1024 * 1024 * 1024;”在大多数当前硬件上将失败,因为该表达式将导致算术溢出。必须写“double storageBytes = 1024. * 1024 * 1024 * 1024;” (3认同)

Ami*_*wad 72

为什么不1000^3呢?

结果1000^3是1003. ^是bit-XOR运算符.

即使它没有处理Q本身,我补充说明.x^y不能总是为x+y,因为它在提问的例子.你必须xor每一点.在示例的情况下:

1111101000? (1000??)
0000000011? (3??)
1111101011? (1003??)
Run Code Online (Sandbox Code Playgroud)

1111101001? (1001??)
0000000011? (3??)
1111101010? (1002??)
Run Code Online (Sandbox Code Playgroud)

  • `^`运算符表示C/C++/Objective-C等中的XOR.在计算器中,它通常表示x-to-the-y功率. (57认同)
  • 这些位确实重叠.但不是1.: - ] (19认同)
  • @Yakk:确实,它看起来错了!......我希望很多人不会认为"A ^ B"总是给A + B(但我担心有些人会......) (6认同)
  • Bah,1000和3的位不重叠.这看起来*错*. (5认同)
  • 先生,我不清楚1003 ^ 3是1003.谷歌和Mac计算器显示1000 ^ 3 = 1,000,000,000.你可以解释吗? (3认同)
  • @OlivierDulac如果人们认为A ^ B意味着A + B并且写前者而不是后者看起来很聪明并且最终会犯错误,他们不应该成为程序员 (3认同)
  • 有趣的事实:XOR **是**无进位加法(二进制,而不是十进制数字)。 (2认同)

chu*_*ica 66

有理由使用1000 * 1000 * 1000.

随着16位int,1000 * 1000溢出.因此使用1000 * 1000 * 1000降低了可移植性.

对于32位int,以下溢出.

long long Duration = 1000 * 1000 * 1000 * 1000;  // overflow
long long Duration = 1000000000000;  // no overflow, hard to read
Run Code Online (Sandbox Code Playgroud)

建议前导值与目标类型匹配,以提高可读性,可移植性正确性.

double Duration = 1000.0 * 1000 * 1000;
long long Duration = 1000LL * 1000 * 1000 * 1000;
Run Code Online (Sandbox Code Playgroud)

也可以简单地使用e符号表示可以完全表示为的值double.当然,这会导致知道是否double可以准确地表示整数值 - 值大于1e9的值.(见DBL_EPSILONDBL_DIG).

long Duration = 1000000000;
// vs.
long Duration = 1e9;
Run Code Online (Sandbox Code Playgroud)

  • 非常重要的评论!https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow可能会帮助很多案件? (5认同)
  • @Patrick'1000`和`1000000000000`都是_integer constants_.每个独立的类型都选自`int`,`long`或`long long`.编译器使用_integer constant_适合的那些3的第一种类型.`1000*1000*1000*1000`用`int`数学作为`int`中的每个`1000`完成.产品溢出32位`int`.`1000000000000`肯定可以表示为"long long"(或者可能更窄) - 没有溢出.目标`long long Duration`的类型不会影响这个"= deuterrination的右侧". (4认同)
  • 在乘法中将较宽的类型放在首位很重要。对于 16 位 `int`,`long x = 1000 * 1000 * 1000L;` 会溢出,而 `long x = 1000L * 1000 * 1000;` 不会。 (3认同)
  • `double` 可以精确地表示最大 2^53 ≈ 9e15 的所有整数。 (2认同)
  • @EdgarBonet确实[binary64](https://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64)可以表示大约9e15的整数.但是C并没有指定使用binary64的`double`,尽管它非常常用.根据C规范,最多1e9左右的值可以准确表示.这取决于您是要编码规范还是依赖常规做法. (2认同)

Tam*_*ola 50

为了便于阅读.

在零(1 000 000 0001,000,000,000)之间放置逗号和空格会产生语法错误,并且1000000000在代码中很难确切地看到有多少个零.

1000*1000*1000很明显它是10 ^ 9,因为我们的眼睛可以更容易地处理块.此外,没有运行时成本,因为编译器将使用常量替换它1000000000.

  • 仅供参考,我最近了解到数字分离器的概念.Java已经有一段时间了,C#7.0可能会得到它.我希望所有语言都具有这种令人眼花缭乱的功能.:) (5认同)
  • @JMS10 C#如果安装VS15预览版已经有了,可以写成`1_000_000_000` (2认同)
  • Python 也将 `_` 作为分隔符 :) (2认同)
  • 而 C++ 最近在 C++14 中得到了 `'` 分隔符,所以你可以使用 `1'000'000'000`。(选择它是因为 `1,000,000,000` 可能会被误解为逗号运算符或 4 个不同的参数,并且 `_1_000_000_000` 是一个有效的(但可能是错误的)变量名。) (2认同)

dje*_*lin 25

为了便于阅读.为了进行比较,Java支持_数量以提高可读性(首先由Stephen Colebourne提出,作为对Derek Foster的PROPOSAL: Project Coin/JSR 334的Binary Literals回复).有人会写1_000_000_000在这里.

大致按时间顺序,从最旧的支持到最新的支持:

这是一种相对较新的功能,语言实现它们应该支持(然后是Perl).正如chux @的优秀答案一样,1000*1000...是一个部分解决方案,但即使最终结果是一个大类型,也会使程序员打开溢出乘法的错误.

  • Ada支持整数文字下划线已有33年了。 (2认同)

Mad*_* Vi 6

可能更容易阅读并获得与1,000,000,000表单的一些关联.

从技术方面来说,我猜直接数或乘法没有区别.无论如何,编译器将生成为十亿亿的数字.

如果你谈论objective-c,那么1000^3就行不通,因为pow没有这样的语法(它是xor).相反,pow()可以使用功能.但在这种情况下,它将不是最优的,它将是运行时函数调用而不是编译器生成的常量.