intptr_t 和 uintptr_t类型使用总结

简介

最近在看代码时,发现了两个之前没见过的数据类型:intptr_tuintptr_t。这两个数据类型是ISO C99定义的,具体代码在linux平台的/usr/include/stdint.h头文件中。

/* Types for `void *' pointers.  */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
typedef long int		intptr_t;
#  define __intptr_t_defined
# endif
typedef unsigned long int	uintptr_t;
#else
# ifndef __intptr_t_defined
typedef int			intptr_t;
#  define __intptr_t_defined
# endif
typedef unsigned int		uintptr_t;
#endif

为什么会根据不同的位数定义不同的长度呢?

先看下不同的数据类型在不同字长机器上长度大小。

位数charshortintlong指针
161个字节8位2个字节16位2个字节16位4个字节32位2个字节16位
321个字节8位2个字节16位4个字节32位4个字节32位4个字节32位
641个字节8位2个字节16位4个字节32位8个字节64位8个字节64位

指针在32位平台和64位平台下均与long 类型的长度一致,然而在16位机器上,long为4个字节,而指针为2个字节。

因此,就可以发现intptr_tuintptr_t定义的巧妙之处:

在64位机器上,intptr_tlong intuintptr_tunsigned long int。而在非64位机器上,intptr_t为int,uintptr_tunsigned int

这样就可以保证intptr_tuintptr_t的长度与机器的指针长度一致,因此在进行整数与 指针的相互转换时可以用intptr_t进行过渡。

下面写两个demo测试下。

测试

一般来讲,我们可能会 习惯性按照以下方式,直接对指针进行强制类型转换。

#include <stdio.h>
#include <stdint.h>

int main()
{
        int a = 12345;    
        int *p = &a;
        int ptr = (int )p;
        printf("%d\n",ptr);
        printf("sizeof(ptr):%ld,sizeof(p):%ld\n",sizeof(ptr),sizeof(p));
        return 0;
}

其实,在编译的时候GCC就已经给出了警告,Wpointer-to-int-cast 意思是将指针转换为整型,二者大小不同。但我们大多数时候可能直接会忽略。

test.c: In function ‘main’:
test.c:13:12: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   13 |  int ptr = (int)p;
      |            ^
➜  code ./test
421252904
sizeof(ptr):4,sizeof(p):8

如果修改下程序

#include <stdio.h>
#include <stdint.h>

int main()

{
        uintptr_t a = 12345;
        uintptr_t *p = &a;
        uintptr_t ptr = (uintptr_t )p;
        printf("%lx\n",ptr);
        printf("sizeof(ptr):%ld,sizeof(p):%ld\n",sizeof(ptr),sizeof(p));
        return 0;
}

再次编译执行就不会警告了。

➜  code ./test            
7ffe06fb7d40
sizeof(ptr):8,sizeof(p):8

同样,将整型转换为指针也是这个道理。

#include <stdio.h>
#include <stdint.h>

int main()

{
        uintptr_t a = 12345;
        uintptr_t *p = (uintptr_t*)a;
        printf("%p\n",p);
        printf("sizeof(a):%ld,sizeof(p):%ld\n",sizeof(a),sizeof(p));
        return 0;
}
➜  code ./test            
0x3039
sizeof(a):8,sizeof(p):8

总结

总结一句话,intptr_tuintptr_r变量类型用于跨平台的情况下,不同机器字长(16位、32位、64位)整数与指针相互转移的的通用性。

本文参考

https://www.136.la/shida/show-382430.html

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
听说这个有用 The following are typedefs of fundamental integral types or extended integral types. signed type unsigned type description intmax_t uintmax_t Integer type with the maximum width supported. int8_t uint8_t Integer type with a width of exactly 8, 16, 32, or 64 bits. For signed types, negative values are represented using 2's complement. No padding bits. Optional: These typedefs are not defined if no types with such characteristics exist.* int16_t uint16_t int32_t uint32_t int64_t uint64_t int_least8_t uint_least8_t Integer type with a minimum of 8, 16, 32, or 64 bits. No other integer type exists with lesser size and at least the specified width. int_least16_t uint_least16_t int_least32_t uint_least32_t int_least64_t uint_least64_t int_fast8_t uint_fast8_t Integer type with a minimum of 8, 16, 32, or 64 bits. At least as fast as any other integer type with at least the specified width. int_fast16_t uint_fast16_t int_fast32_t uint_fast32_t int_fast64_t uint_fast64_t intptr_t uintptr_t Integer type capable of holding a value converted from a void pointer and then be converted back to that type with a value that compares equal to the original pointer. Optional: These typedefs may not be defined in some library implementations.* Some of these typedefs may denote the same types. Therefore, function overloads should not rely on these being different. * Notice that some types are optional (and thus, with no portability guarantees). A particular library implementation may also define additional types with other widths supported by its system. In any case, if either the signed or the unsigned version is defined, both the signed and unsigned versions are defined.
[SuppressUnmanagedCodeSecurity]         internal static class SafeNativeMethods         {             // 创建一个libvlc实例,它是引用计数的               [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]             internal static extern libvlc_instance_t libvlc_new(int argc, IntPtr argv);             // 释放libvlc实例               [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]             internal static extern void libvlc_release(libvlc_instance_t libvlc_instance);             //获取libvlc的版本               [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]             internal static extern String libvlc_get_version();             //从视频来源(例如http、rtsp)构建一个libvlc_meida               [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]             internal static extern libvlc_media_t libvlc_media_new_location(libvlc_instance_t libvlc_instance, IntPtr path);             //从本地文件路径构建一个libvlc_media               [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]             internal static extern libvlc_media_t libvlc_media_new_path(libvlc_instance_t libvlc_instance, IntPtr path);             //释放libvlc_media               [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]             internal static extern void libvlc_media_release(libvlc_media_t libvlc_media_inst);             // 创建一个空的播放器               [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]             internal static extern libvlc_media_player_t libvlc_media_player_new(libvlc_instance_t libvlc_instance);             //从libvlc_media构建播放器               [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]             internal static extern libvlc_media_player_t libvlc_media_playe

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式与Linux那些事

您的鼓励将使我写出更好的文章

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值