我很困惑sprintf,一个有趣的问题与不同的平台。 代码:
int main () { char sql[1024]; uint32_t app_id = 32; uint64_t task_id = 64; sprintf(sql, "%u, %u", task_id, app_id); printf ("%s\n", sql); return 0; }
控制台(MSVC2010debugging/版本)中的结果:64,0
但是在控制台(CentOS64 gcc4.4.6)中的代码相同:64,32
任何人都会帮我的!
– – – – – – -更新 – – – – – – – – – – – – –
多谢你们。 我读过这篇文章: sprintf for unsigned _int64
实际上, "inttypes.h"
I64u
定义了: I64u
不支持的I64u
。 所以我可以这样写:
sprintf(sql, "%I64u, %I32u", task_id, app_id);
在sprintf()
使用%llu
格式字符串作为task_id
,如下所示:
sprintf(sql, "%llu, %u", task_id, app_id); // ^ // for: long long unsigned int
编辑:由于@ Simonc建议最好使用:在<inttypes.h>
定义的PRIu32
和PRIu64
宏(因为你有Linux标签)就像:
sprintf(sql, "%"PRIu64", %"PRIu32"", task_id, app_id); // ^ ^ // for: uint64_t uint32_t
格式化字符串%lu
不适用于64位变量很long long
32位机器。
使用%llu
替代64位:
#include <stdio.h> #include <stdlib.h> #include <linux/types.h> #include <stdint.h> int main () { char sql[1024]; uint32_t app_id = 32; uint64_t task_id = 64; sprintf(sql, "%llu, %u", task_id, app_id); printf ("%s\n", sql); return 0; }
尝试:
sprintf(sql, "%lu, %u", task_id, app_id);
正如已经指出的, uint64_t
的正确的格式说明符是PRIu64
( 不是 lu
,因为不能保证uint64_t
很long
)。
所以,你需要使用:
#define __STDC_FORMAT_MACROS #include <inttypes.h> char sql[1024]; uint32_t app_id = 32; uint64_t task_id = 64; sprintf(sql, "%u, %" PRIu64, app_id, task_id); printf ("%s\n", sql);
只是增加别人的话:
给予
sprintf(sql, "%u, %u", app_id, task_id);
代替
sprintf(sql, "%u, %u", task_id, app_id);
给出输出32, 64
!
不用担心! 这是为什么:在推送app_id
(作为sprintf
参数)之前, task_id
被压入堆栈(高4字节,低4字节秒)。 但是当sprintf
接受参数时,它会从堆栈中弹出4个字节+ 4个字节,因为在格式中指定了两个%u。 所以它需要task_id
的低4个字节并将其打印为unsigned int
。
sprintf(sql, "%u, %u", task_id, app_id);
给出。
app_id
推送task_id
接下来推送task_id
。 但是当sprintf读取时,它弹出两个4字节, 64
(task_id的低4字节)和00
(高4字节的task_id
并打印task_id
。
格式说明符是错误的。 printf
函数不知道传递给它的是什么类型的参数,它只能从格式说明符中推导出来。 所以,当你传递一个64位的整数,并告诉函数,你只通过一个很长的(32位),那么只需要传入64位值的一半。根据架构,正确的结果可能会打印与否。 原因是数字如何存储在内存中,以及printf函数在读取long
值时看到的是什么。
如果long值碰巧具有相同的比特数,或者将值存储在内存中,以致预期的结果恰好在正确的位置,则可以打印正确的值,但是当然,代码仍然会是错误的,尽管它似乎工作。