__int64 类型(VC中)与long long 型(gcc中,C99标准)

本文介绍了不同编译器下64位整数的表示方法及其输入输出方式,包括C#中的Int64、C/C++中的__int64及long long等数据类型,并对比了VC6.0与g++编译器的处理差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

  • int64 是有符号 64 位整数数据类型,也就是 C# 中的 long 和 SQL Server 中的 bigint,范围为 -2^63 (-9,223,372,036,854,775,808) 到 2^63-1 (9,223,372,036,854,775,807),存储空间占 8 字节。用于整数值可能超过 int 数据类型支持范围的情况。

    c#中:

    Int64 值类型表示值介于 -9,223,372,036,854,775,808 到 +9,223,372,036,854,775,807 之间的整数。

     

    Int64 为比较此类型的实例、将实例的值转换为它的字符串表示形式以及将数字的字符串表示形式转换为此类型的实例提供了相应的方法。

     

    警告 在 32 位 Intel 计算机上分配 64 位值不是原子操作;即该操作不是线程安全的。这意味着,如果两个人同时将一个值分配给一个静态 Int64 字段,则该字段的最终值是无法预测的。

    有关格式规范代码如何控制值类型的字符串表示形式的信息,请参见格式化概述。此类型实现接口 IComparable、IFormattable 和 IConvertible。使用 Convert 类进行转换,而不是使用此类型的 IConvertible 显式接口成员实现。

     C语言INT64  (VC中)

    __int64 是一个关键字,用_int64 来可以指定一个64位的整型变量 

    __int8 nSmall;      // 声明 8位 整数 

    __int16 nMedium;    // 声明 16位 整数 

    __int32 nLarge;     // 声明 32位 整数 

    __int64 nHuge;      // 声明 64位 整数 

      

    long   long是C99标准的C语言内置类型。需要符合C99的编译器

     g++ /gcc中

    long long a; 

    printf("%lld",a);  

    mingw32 中

    __int64 a; 

    printf("%I64d",a);  

    源文档 <http://blog.youkuaiyun.com/luxuejuncarl/archive/2007/04/18/1568457.aspx>

     

 

  • 在做ACM题时,经常都会遇到一些比较大的整数。而常用的内置整数类型常常显得太小了:其中long 和 int 范围是[-2^31,2^31),即-2147483648~2147483647。而unsigned范围是[0,2^32),即0~4294967295。也就是说,常规的32位整数只能够处理40亿以下的数。

    那遇到比40亿要大的数怎么办呢?这时就要用到C++的64位扩展了。不同的编译器对64位整数的扩展有所不同。基于ACM的需要,下面仅介绍VC6.0与g++编译器的扩展。

    VCVC6.0的64位整数分别叫做__int64与unsigned __int64,其范围分别是[-2^63, 2^63)与[0,2^64),即-9223372036854775808~9223372036854775807与0~18446744073709551615(约1800亿亿)。对64位整数的运算与32位整数基本相同,都支持四则运算与位运算等。当进行64位与32位的混合运算时,32位整数会被隐式转换成64位整数。但是,VC的输入输出与__int64的兼容就不是很好了,如果你写下这样一段代码:

    1

    __int64 a;

    2

    cin >> a;

    3

    cout << a;

    那么,在第2行会收到“error C2679: binary '>>' : no operator defined which takes a right-hand operand of type '__int64' (or there is no acceptable conversion)”的错误;在第3行会收到“error C2593: 'operator <<' is ambiguous”的错误。那是不是就不能进行输入输出呢?当然不是,你可以使用C的写法:

    scanf("%I64d",&a);

    printf("%I64d",a);

    就可以正确输入输出了。当使用unsigned __int64时,把"I64d"改为"I64u"就可以了。

    OJ通常使用g++编译器。其64位扩展方式与VC有所不同,它们分别叫做long long 与 unsigned long long。处理规模与除输入输出外的使用方法同上。对于输入输出,它的扩展比VC好。既可以使用

    1

    long long a;

    2

    cin>>a;

    3

    cout<<a;

    也可以使用

    scanf("%lld",&a);

    printf("%lld",a);

    使用无符号数时,将"%lld"改成"%llu"即可。

    最后我补充一点:作为一个特例,如果你使用的是Dev-C++的g++编译器,它使用的是"%I64d"而非"%lld"。

     

    源文档 <http://jdzzgtc.blog.163.com/blog/static/1631216220099814450401/>

     

<think>好的,用户现在想了解C++ stdlib.h中的rand函数的实现和源码,以及在哪里可以找到这些源码。首先,我需要回忆一下C标准库中rand函数的常见实现方式。通常,rand使用的是线性同余生成器(LCG),但不同的编译器可能有不同的实现,比如glibc、MSVC或者LLVM的libc++。 接下来,用户可能想知道具体的源码在哪里查找。我需要分别说明不同编译器的源码位置,比如glibc可以在其Git仓库中找到,而MSVC可能需要通过Visual Studio安装目录或者官方文档。同时,用户可能对实现的细节感兴趣,比如算法原理、种子处理和线程安全问题。 需要确认用户是否有特定的编译器环境,比如是否在使用GCC、Clang还是MSVC,因为不同实现的代码路径不同。另外,用户可能想知道如何查看自己系统中使用的rand函数的具体实现,可能需要指导他们查看本地安装的源码或者在线资源。 还需要注意,直接查看标准库源码对于新手来说可能有些困难,所以可能需要给出具体的代码示例或算法步骤,帮助理解。此外,提醒用户rand函数的局限性和C++11推荐的替代方案,比如<random>库,可能也是有帮助的。 最后,确保回答结构清晰,分点说明不同编译器的实现和源码位置,并解释算法原理,同时给出示例代码和注意事项。需要避免过于技术化的术语,但保持准确性,确保用户能够理解并找到所需的信息。</think>在 C/C++ 中 `rand()` 函数的实现因编译器而异,以下是常见实现的深度解析: --- ### **一、核心实现原理** 主流实现普遍采用 **线性同余生成器(LCG)** 算法: $$ X_{n+1} = (a \times X_n + c) \mod m $$ 其中: - $a$ = 乘数(multiplier) - $c$ = 增量(increment) - $m$ = 模数(决定取值范围) - $X_0$ = 种子(由 `srand()` 设置) --- ### **二、不同编译器的具体实现** #### **1. GNU glibc 实现(Linux/GCC)** 路径:`glibc/stdlib/random_r.c` ```c // 典参数:a=1103515245, c=12345, m=2^31 int __random_r (struct random_data *buf, int32_t *result) { int32_t *state = buf->state; int32_t val = state[0]; val = ((state[0] * 1103515245) + 12345) & 0x7fffffff; state[0] = val; *result = val; return 0; } ``` 特点:使用 31 位精度(高位被截断) #### **2. Microsoft VC++ 实现** 路径:`%VS安装路径%/VC/crt/src/rand.c` ```c // 经典参数:a=214013, c=2531011, m=2^32 void __cdecl srand(unsigned int seed) { _getptd()->_holdrand = (unsigned long)seed; } int __cdecl rand(void) { _ptiddata ptd = _getptd(); return( ((ptd->_holdrand = ptd->_holdrand * 214013L + 2531011L) >> 16) & 0x7fff ); } ``` 特点:返回值的有效位数仅 15 位 #### **3. LLVM libc++ 实现(macOS/Clang)** 路径:`libc/src/stdlib/rand.cpp` ```c static unsigned long next = 1; int rand(void) { next = next * 1103515245 + 12345; return (unsigned int)(next / 65536) % 32768; } void srand(unsigned int seed) { next = seed; } ``` 特点:保留传统 BSD 实现方式 --- ### **三、源码获取途径** 1. **GNU glibc**: - 在线浏览:https://sourceware.org/git/?p=glibc.git - 本地安装:`apt-get source glibc-source`(Debian/Ubuntu) 2. **MSVC CRT**: - Visual Studio 安装目录:`VC\crt\src` - 开源版本:https://github.com/microsoft/STL 3. **LLVM libc++**: - 官方仓库:https://github.com/llvm/llvm-project/tree/main/libcxx 4. **在线工具**: - Compiler Explorer:https://godbolt.org/(可查看汇编实现) --- ### **四、关键实现细节** 1. **线程安全性**: - glibc 使用 `__thread` 实现线程局部存储 - MSVC 通过 `_getptd()` 获取线程私有数据 2. **种子处理**: ```c // 典种子初始化(未设置时默认种子为1) unsigned long _holdrand = 1; // 时间种子示例 srand((unsigned)time(NULL)); ``` 3. **范围限制**: - 通过位掩码实现范围控制 - 例如:`& 0x7FFF` 得到 0-32767 的数值 --- ### **五、算法局限性** 1. **周期性重复**:所有 LCG 实现都有周期限制(如 glibc 的周期为 $2^{31}$) 2. **低位随机性差**:建议使用高位比特(如 `rand() >> 16`) 3. **非加密安全**:可通过观察输出序列推测种子 --- ### **六、现代替代方案(C++11+)** ```cpp #include <random> std::mt19937_64 engine(std::random_device{}()); std::uniform_int_distribution<int> dist(0,99); int val = dist(engine); // 高质量随机数 ``` --- ### **七、快速测试示例** ```cpp #include <iostream> #include <cstdlib> int main() { srand(1); // 固定种子可复现序列 for(int i=0; i<5; ++i) { std::cout << rand() << " "; } // 典输出(glibc): 1804289383 846930886 1681692777... } ``` --- ### **附:历史演进** - 1988 ANSI C:首次标准化 - 1999 C99:明确要求至少 32767 的 RAND_MAX - 2011 C++11:推荐使用 `<random>` 替代 建议需要高质量随机数时优先使用 C++11 的 `<random>` 库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值