我的源代码中有相当多的代码,但主要问题是连续两行代码。
struct step
{
int left,tonum;
long long int rez;
};
inline bool operator==(const step& a, const step& b)
{
printf("\n%d",b.tonum);
printf("\n%d %d | %d %d | %d %d",a.left, b.left, a.rez, b.rez, a.tonum, b.tonum);
return a.left==b.left && a.rez==b.rez && a.tonum==b.tonum;
}这被调用了数百万次,但问题是,尽管大多数时候应该是相同的,但从来没有,而且输出是非常奇怪的。
2
7989 7989 | 53 0 | 53 0
1
8989 7989 | 52 0 | 53 0
2
8989 8989 | 52 0 | 52 0
1
7899 8989 | 51 0 | 52 0b.tonum不仅应该是相同的,而且他也应该是== a.tonum,因为在这段代码中没有解释的其他一些原因
为什么b.tonum两次打印都不一样?
发布于 2014-01-10 03:15:56
不能使用%d打印long long。你必须使用%lld。(所以使用"\n%d %d | %lld %lld | %d %d"作为您的格式字符串。)
特别是,很明显,在"52 0\ 52 0“中,前52 0是a.rez,第2 52 0是b.rez (其中每一个都是long long,显然是(从输出来看)将两个单词推到堆栈中)。a.tonum和b.tonum根本没有打印。
为了理解为什么会发生这种情况,让我解释一下乔纳森和我想说的话。当您调用像printf这样的变量函数(声明为类似于printf(const char *format, ...)的函数)时,编译器无法在编译时验证...的正确参数类型。因此,在这种情况下,有一个决定在堆栈上推入什么的过程,大致可以概括为:如果它是int或可升级到int,则它被作为int推送;如果它是double或可提升到double,则它被推送为double;否则,它按原样推送。
在实现像printf这样的变量函数时,您需要某种方式来访问...项。这样做的方法是使用va_list,这是在<stdarg.h>中声明的。下面是一些伪代码,它展示了如何使用它:
int printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
while (/* we find the next format marker */) {
if (/* %d, %i, %c */) {
int val = va_arg(ap, int);
/* print out val as decimal or (for %c) char */
} else if (/* %u, %x, %X, %o */) {
unsigned int val = va_arg(ap, unsigned int);
/* print out val as decimal, hex, or octal */
} else if (/* %ld, %li */) {
long val = va_arg(ap, long);
/* print out val as decimal */
} else if (/* %lu, %lx, %lX, %lo */) {
unsigned long val = va_arg(ap, unsigned long);
/* print out val as decimal, hex, or octal */
} else if (/* %lld, %lli */) {
long long val = va_arg(ap, long long);
/* print out val as decimal */
} else if (/* %llu, %llx, %llX, %llo */) {
unsigned long long val = va_arg(ap, unsigned long long);
/* print out val as decimal, hex, or octal */
} else if (/* %s */) {
const char *val = va_arg(ap, const char *);
/* print out val as null-terminated string */
} /* other types */
}
va_end(ap);
return /* ... */;
}注意,每次您想取掉一个...参数时,都要使用va_arg,并且必须指定要选择的类型。这取决于你挑出正确的类型。如果类型不正确,则会出现类型双关情况,在大多数情况下,这种情况下都有未定义的行为(这意味着程序可以做它喜欢的任何事情,包括崩溃或更糟)。
在您的特定计算机中,似乎当您传递一个long long时,它将64位数量推到堆栈中,但是由于您使用了%d格式说明符,所以它使用的是va_arg(ap, int)版本,该版本只获取32位数量。这意味着64位单词的另一半仍然未读,随后的%d继续读。这就是为什么当格式字符串完成时,它从未处理您传递的a.tonum和b.tonum的值。
然而,如果您正确地使用了%lld,它就会使用va_arg(ap, long long),并且将正确地读取整个64位的数量。
https://stackoverflow.com/questions/21035568
复制相似问题