我在MinGW中有以下c++源代码测试,g++版本是4.8.1 : compiled : 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是正确的!但是我不知道是什么导致了这个问题,我应该修改什么才能正确地使用原子...thanks!
发布于 2013-06-20 13:05:04
您使用的行打印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尝试访问由uint64_t指定的vararg时,当实际传递的参数是uint64_t时,结果将是未定义的行为。
printf的常规格式化程序(如%d和%llu )用于内置类型,如int或unsigned long long。stdint.h中的类型不是内置的,可能对应于不同平台上的不同内置类型,在每个平台上需要不同的格式化程序。
例如,在一个平台上,int64_t可能与int相同,而在另一个平台上,int64_t可能与long long相同。由于要在printf中使用int如果使用格式说明符%d,要使用long long则使用格式说明符%lld,因此不能使用标准类型和普通格式说明符编写可移植代码。
相反,头文件inttyes.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库的一个优点是这种错误是不可能的。
https://stackoverflow.com/questions/17204625
复制相似问题