我在winx中的MinGW中有以下c ++源代码测试,g ++版本是4.8.1: 编译:g ++ -std = c ++ 11 int64test.cpp -o int64test.exe
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
#include <errno.h>
#include <atomic>
#include <iostream>
#include <cstdint>
using namespace std ;
int main(int argc, const char *argv[])
{
atomic<unsigned int> uintlocal1(1000) ;
unsigned int uint1,uint2,uint3 ;
uint1 = uintlocal1.fetch_add(1) ;
uint2 = uintlocal1.fetch_add(1) ;
uint3 = uintlocal1.fetch_add(1) ;
printf("(%d)(%d)(%d)(%d)\n",uint1,uint2,uint3,unsigned(uintlocal1)) ;
atomic<uint64_t> uint64local1(1000) ;
uint64_t u1,u2,u3 ;
u1 = uint64local1.fetch_add(1) ;
u2 = uint64local1.fetch_add(1) ;
u3 = uint64local1.fetch_add(1) ;
printf("(%d)(%d)(%d)(%d)\n",u1,u2,u3,unsigned(uint64local1)) ;
}
答案是:
(1000)(1001)(1002)(1003)
(1000)(0)(1001)(0)
显然,原子uint64_t是错误的,而原子int是对的!! 但我不知道是什么导致这个问题,我应该修改什么才能使我 可以正确使用原子...谢谢!!
答案 0 :(得分:2)
您使用的行格式uint64_t
数据格式不正确。当我编译你的代码时,我的编译器会产生以下警告:
main.cpp:18:33: warning: format specifies type 'int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]
printf("(%d)(%d)(%d)(%d)\n",u1,u2,u3,unsigned(uint64local1)) ;
~~ ^~
%llu
main.cpp:18:36: warning: format specifies type 'int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]
printf("(%d)(%d)(%d)(%d)\n",u1,u2,u3,unsigned(uint64local1)) ;
~~ ^~
%llu
main.cpp:18:39: warning: format specifies type 'int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]
printf("(%d)(%d)(%d)(%d)\n",u1,u2,u3,unsigned(uint64local1)) ;
~~ ^~
%llu
注意:您可以使用标记-Wformat
或更好的-Wall
在GCC 4.8.1中启用类似的格式检查警告。
在我的平台上,int
和unsigned long long
类型不兼容布局,因此当实际传递的参数为%d
时,printf尝试访问由uint64_t
指定的vararg结果将是未定义的行为。
printf的常规格式化程序(例如%d
和%llu
)用于内置类型,例如int
或unsigned long long
。 stdint.h中的类型不是内置的,可能对应不同平台上的不同内置类型,每个平台需要不同的格式化程序。
例如int64_t
可能与一个平台上的int
相同,而另一个平台上的long long
则相同。由于在printf中使用int
使用格式说明符%d
并使用long long
使用格式说明符%lld
,因此无法使用stdint类型和正常编写可移植代码格式说明符。
相反,标头inttypes.h提供了包含正确格式说明符的宏。 uint64_t
的宏是PRIu64。此宏将定义为平台上正确的格式说明符。像这样使用它:
printf("(%" PRIu64 ")(%" PRIu64 ")(%" PRIu64 ")(%u)\n",u1,u2,u3,unsigned(uint64local1));
确保在宏和引用的字符串片段之间放置空格,否则在C ++ 11中宏将无法正常工作。
以下是普通格式化程序的有用参考:http://en.cppreference.com/w/cpp/io/c/fprintf
以下是stdint.h类型和格式化程序的参考:http://en.cppreference.com/w/cpp/types/integer
注意:对printf使用不正确的格式说明符很容易造成错误并导致未定义的行为。 iostream库的一个优点是这种错误是不可能的。