这是一个用于计算素数的小代码,使用gcc(Debian 8.3.0-6)8.3.0进行编译当我使用int64_t p = 0
时,它可以正常工作。使用int64_t p
,它会工作错误。这是什么问题?
变量p
将通过使用scanf
分配
用int64_t p = 0
确定:
gcc t.c && ./a.out
input a prime:3
i:2 < number:3
3 is a prime, again
int64_t p
错误:
gcc t.c && ./a.out
input a prime:3
i:2 < number:3
i:3 < number:3
i:4 < number:3
i:5 < number:3
i:6 < number:3
i:7 < number:3
i:8 < number:3
i:9 < number:3
i:10 < number:3
i:11 < number:3
i:12 < number:3
i:13 < number:3
3 not a prime, again
#include <stdint.h>
#include <stdio.h>
int32_t isPrime(int64_t number)
{
int64_t i = 2;
for(; i < number; i++)
{
printf("i:%d < number:%d\n",i, number);
if((number % i) == 0)
return 0;
if ((i * i) >= number)
break;
}
return 1;
}
int32_t main(void)
{
int64_t t = 0;
int64_t p;
//int64_t p = 0;
printf("input a prime:");
do
{
scanf("%d",&p);
getchar();
if (isPrime(p))
printf("%d is a prime, again:", p);
else
printf("%d not a prime, again:", p);
}while(1);
}
您已将p
声明为int64_t
,但%d
表示int
。 int64_t
和其他stdint.h
类型的转换说明符位于inttypes.h
中:
#include <inttypes.h>
scanf("%" SCNd64, &p);
类似地,在打印时(使用正确的说明符会向您显示问题):
printf("i:%" PRId64 " < number:%" PRId64 "\n", i, number);
这两个错误都是优秀的编译器应该能够警告您的东西-例如,clang默认会这样做。如果您使用的是gcc,请确保至少使用gcc -Wall
进行编译。
此外,检查scanf
的返回值以确保成功是个好主意。如果您不希望进行更深层次的恢复,则最好退出其他方法。
if (scanf("%" SCNd64, &p) != 1) {
return EXIT_FAILURE;
}
最后,main
的正确返回类型是int
,而不是int32_t
。
此(scanf("%d",&p);
)是读取int64_t
的错误代码。形式上,您需要scanf("%" SCNd64, &p)
-和<inttypes.h>
(而不是<stdint.h>
或与之相同)。
您可能不愿使用scanf("%lld", &p);
,因为在大多数计算机上,int64_t
是long long
的同义词。
使用结果前,您还应检查scanf()
返回1
。
初始化p
时,您会得到p
调用设置的scanf()
的“正确”部分,因为您使用的是低端字节序的计算机,而其余部分则为零。但是这样做会引起不确定的行为。什么事情都可能发生。它是不可移植的(它可能不会在big-endian机器上做您想要的事情),并且由于它的不确定性而完全不可靠。