C 中的 long long 乘法给出错误的结果

long long multiplication in C gives wrong result

我的 C 代码似乎出现了故障,无法将很长的数字相乘并输出结果,而且我无法弄清楚为什么。

这是罪魁祸首代码:

#include "stdio.h"

int main()
{
  unsigned long long primes[] = {199453LL, 200723LL, 203317LL, 205103LL, 206603LL, 208057LL, 210323LL, 210961LL, 212827LL, 214237LL, 215693LL, 216319LL};
  unsigned long long numbers[6];

  int i;
  printf("Calculating the numbers to factor!\n");
  printf("Size of long: %i\n", sizeof(long));
  printf("Size of long long: %i\n", sizeof(long long));
  for (i = 0; i < 6; i++)
  {
    numbers[i] = primes[i]*primes[11-i];
    printf("%ld*%ld = %ld\n", primes[i], primes[11-i], numbers[i]);
    printf("Result is %ld\n",numbers[i]);
  }

  return 0;
}

这是我编译它和 运行 时的输出(我在 Linux 上使用 gcc 4.8.2 版)

Calculating the numbers to factor!
Size of long: 4
Size of long long: 8
199453*0 = 216319
Result is 195800547
200723*0 = 215693
Result is 344873079
203317*0 = 214237
Result is 608351169
205103*0 = 212827
Result is 701783221
206603*0 = 210961
Result is 635502523
208057*0 = 210323
Result is 809499451

您的 printf 格式字符串有误。 %ld需要一个long int%lld是一个long long int,既然你用的是unsigned long long,你应该用%llu,否则大正值将显示为负数。

而且,正如 所注意到的,size_t (sizeof) 需要 %zu

来自 printf(3):

l (ell) A following integer conversion corresponds to a long int or unsigned long int argument, or a following n conversion corresponds to a pointer to a long int argument, or a following c conversion corresponds to a wint_t argument, or a following s conversion corresponds to a pointer to wchar_t argument.

ll (ell-ell). A following integer conversion corresponds to a long long int or unsigned long long int argument, or a following n conversion corresponds to a pointer to a long long int argument.

...

z A following integer conversion corresponds to a size_t or ssize_t argument. (Linux libc5 has Z with this meaning. Don't use it.)


现在,例如这个输出

199453*0 = 216319

发生是因为小端64位数字199453、216319和43145473507被正确压入堆栈;但是 printf 期望在堆栈上只找到 32 位数字,因此它打印 199453、0(这是 64 位数字 199453 的前 4 个字节)和 216319。