intptr_t详解

看leveldb代码时候发现inptr_t居然不知道是啥,搜索了一番发现一个比较官方的解释

尽管大部分程序员习惯自由使用标准类型, 如 int 和 long, 编写设备驱动需要一些小心来避免类型冲突和模糊的 bug.

这个问题是你不能使用标准类型, 当你需要"一个 2-字节 填充者"或者"一个东西来代表一个4-字节 字串", 因为正常的 C 数据类型在所有体系上不是相同大小. 为展示各种 C 类型的数据大小, datasize 程序已包含在例子文件 misc-progs 目录中, 由 O' Reilly's FTP 站点提供. 这是一个程序的样例运行, 在一个 i386 系统上(显示的最后 4 个类型在下一章介绍):

morgana% misc-progs/datasize
arch Size: char short int long ptr long-long u8 u16 u32 u64
i686       1    2     4   4    4   8         1  2   4   8

这个程序可以用来显示长整型和指针在 64-位 平台上的不同大小, 如同在不同 Linux 计算机上运行程序所演示的:

arch  Size:  char  short  int  long  ptr long-long  u8 u16 u32 u64 
i386         1     2      4    4     4   8          1  2   4   8  
alpha        1     2      4    8     8   8          1  2   4   8  
armv4l       1     2      4    4     4   8          1  2   4   8  
ia64         1     2      4    8     8   8          1  2   4   8  
m68k         1     2      4    4     4   8          1  2   4   8  
mips         1     2      4    4     4   8          1  2   4   8  
ppc          1     2      4    4     4   8          1  2   4   8  
sparc        1     2      4    4     4   8          1  2   4   8  
sparc64      1     2      4    4     4   8          1  2   4   8  
x86_64       1     2      4    8     8   8          1  2   4   8  

注意有趣的是 SPARC 64 体系在一个 32-位 用户空间运行, 因此那里指针是 32 位宽, 尽管它们在内核空间是 64 位宽. 这可用加载 kdatasize 模块(在例子文件的 misc-modules 目录里)来验证. 这个模块在加载时使用 printk 来报告大小信息, 并且返回一个错误( 因此没有必要卸载它 ):

kernel: arch Size: char short int long ptr long-long u8 u16 u32 u64
kernel: sparc64    1    2     4   8    8   8         1  2   4   8
尽管在混合不同数据类型时你必须小心, 有时有很好的理由这样做. 一种情况是因为内存存取, 与内核相关时是特殊的. 概念上, 尽管地址是指针, 内存管理常常使用一个无符号的整数类型更好地完成; 内核对待物理内存如同一个大数组, 并且内存地址只是一个数组索引. 进一步地, 一个指针容易解引用; 当直接处理内存存取时, 你几乎从不想以这种方式解引用. 使用一个整数类型避免了这种解引用, 因此避免了 bug. 因此, 内核中通常的内存地址常常是 unsigned long, 利用了指针和长整型一直是相同大小的这个事实, 至少在 Linux 目前支持的所有平台上.

因为其所值的原因, C99 标准定义了 intptr_t 和 uintptr_t 类型给一个可以持有一个指针值的整型变量. 但是, 这些类型几乎没在 2.6 内核中使用.

总而言之就是:intptr_t是为了跨平台,其长度总是所在平台的位数,所以用来存放地址。

参考:http://www.cnblogs.com/Anker/p/3438480.html

/* There is some amount of overlap with <sys/types.h> as known by inet code */
#ifndef __int8_t_defined
# define __int8_t_defined
typedef signed char         int8_t;
typedef short int          int16_t;
typedef int               int32_t;
# if __WORDSIZE == 64
typedef long int          int64_t;
# else
__extension__
typedef long long int        int64_t;
# endif
#endif

/* Unsigned.  */
typedef unsigned char         uint8_t;
typedef unsigned short int    uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int          uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int       uint64_t;
#else
__extension__
typedef unsigned long long int    uint64_t;
#endif

/* 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


<think>我们被要求回答关于`_finddata_t`结构体的使用方法和介绍。根据提供的引用,我们可以汇总以下信息: 1. **结构体作用**:`_finddata_t`结构体用于存储文件的各种信息(如属性、时间、大小、文件名等)[^1][^4]。 2. **成员变量**(引用[4]详细说明): - `unsigned attrib`:文件属性(存档、隐藏、正常、只读、文件夹、系统等,通过位或组合)。 - `time_t time_create`:文件创建时间。 - `time_t time_access`:最后一次访问时间。 - `time_t time_write`:最后一次修改时间。 - `_fsize_t size`:文件大小(字节数)。 - `char name[_MAX_FNAME]`:文件名(`_MAX_FNAME`是最大文件名长度常量)。 3. **使用流程**(引用[2][3]): - 使用`_findfirst`函数开始查找,返回一个句柄(`intptr_t`类型)和第一个文件的信息(填充到`_finddata_t`结构体)。 - 使用`_findnext`函数查找下一个文件,需要传入`_findfirst`返回的句柄和`_finddata_t`结构体指针。 - 查找完成后,使用`_findclose`关闭句柄。 4. **典型代码框架**(引用[3]提供了示例代码): ```c++ #include <io.h> #include <iostream> #include <vector> using namespace std; void findFiles(const string& path, const string& extension, vector<string>& files) { // 构造查找模式:路径 + "/*." + 扩展名 string pattern = path + "/*." + extension; _finddata_t fileInfo; intptr_t hFile = _findfirst(pattern.c_str(), &fileInfo); if (hFile != -1) { do { // 跳过子目录 . 和 .. if (strcmp(fileInfo.name, ".") != 0 && strcmp(fileInfo.name, "..") != 0) { // 如果是子目录,可以递归遍历;如果是文件,则加入列表 if (fileInfo.attrib & _A_SUBDIR) { // 如果是子目录,递归遍历 string subPath = path + "/" + fileInfo.name; findFiles(subPath, extension, files); } else { files.push_back(path + "/" + fileInfo.name); } } } while (_findnext(hFile, &fileInfo) == 0); _findclose(hFile); } } ``` **注意**:上述代码示例增加了跳过"."和".."的逻辑,并处理了子目录的递归遍历(但原示例中没有递归,这里扩展了一下)。 5. **属性常量**(引用[4]提到): - `_A_ARCH`:存档文件。 - `_A_HIDDEN`:隐藏文件。 - `_A_NORMAL`:正常文件。 - `_A_RDONLY`:只读文件。 - `_A_SUBDIR`:目录(文件夹)。 - `_A_SYSTEM`:系统文件。 **总结使用步骤**: 1. 包含头文件`<io.h>`(在Windows环境下)。 2. 声明`_finddata_t`结构体变量。 3. 使用`_findfirst`开始查找,传入文件匹配模式(如`"C:\\folder\\*.*"`)和结构体指针,得到句柄。 4. 如果句柄有效(不为-1),则循环调用`_findnext`直到返回非0(表示没有更多文件)。 5. 在循环中处理每个文件(根据属性判断类型,获取文件名等)。 6. 关闭句柄(`_findclose`)。 **注意事项**: - 这个函数是平台相关的(Windows),在Linux下使用`dirent.h`。 - 文件名匹配模式中可以使用通配符(如`*`和`?`)。 - 遍历时,通常需要跳过当前目录(`.`)和上级目录(`..`),避免重复遍历。 根据以上信息,我们可以组织回答。 </think>### `_finddata_t`结构体详解及使用方法 `_finddata_t`是Windows平台下用于文件查找的核心结构体,需配合`_findfirst`、`_findnext`和`_findclose`函数使用。以下是详细说明: #### 结构体成员定义[^4] ```c++ struct _finddata_t { unsigned attrib; // 文件属性(位标志组合) __time64_t time_create; // 创建时间(64位时间戳) __time64_t time_access; // 最后访问时间 __time64_t time_write; // 最后修改时间 _fsize_t size; // 文件大小(字节数) char name[260]; // 文件名(MAX_PATH长度) }; ``` **属性常量**(通过位或`|`组合): - `_A_ARCH`:存档文件 - `_A_HIDDEN`:隐藏文件 - `_A_NORMAL`:常规文件 - `_A_RDONLY`:只读文件 - `_A_SUBDIR`:文件夹(目录) - `_A_SYSTEM`:系统文件 #### 使用流程[^2][^3] 1. **初始化查找** 使用`_findfirst`获取首个文件句柄: ```c++ _finddata_t fileInfo; intptr_t hFile = _findfirst("C:\\folder\\*.txt", &fileInfo); if(hFile == -1) { /* 错误处理 */ } ``` 2. **遍历文件** 循环调用`_findnext`获取后续文件: ```c++ do { // 跳过"."和".."目录 if(strcmp(fileInfo.name, ".") != 0 && strcmp(fileInfo.name, "..") != 0) { cout << "文件名:" << fileInfo.name << " 大小:" << fileInfo.size << "字节" << endl; } } while(_findnext(hFile, &fileInfo) == 0); ``` 3. **关闭句柄** 结束时必须释放资源: ```c++ _findclose(hFile); ``` #### 典型应用场景 ```c++ #include <io.h> #include <vector> using namespace std; vector<string> findFiles(const string& path, const string& ext) { vector<string> files; _finddata_t fd; string pattern = path + "/*." + ext; intptr_t h = _findfirst(pattern.c_str(), &fd); if(h != -1) { do { // 跳过目录并匹配扩展名 if(!(fd.attrib & _A_SUBDIR) && strstr(fd.name, ext.c_str())) { files.push_back(string(fd.name)); } } while(_findnext(h, &fd) == 0); _findclose(h); } return files; } ``` > 此函数返回指定目录中所有扩展名为`ext`的文件列表[^3]。 #### 注意事项 1. 文件路径需用双反斜杠`\\`或正斜杠`/` 2. 通配符规则: - `*` 匹配任意字符(如`*.cpp`) - `?` 匹配单个字符(如`image??.png`) 3. 时间戳需用`_localtime64_s()`转换为可读格式 4. 属性检查示例: ```c++ if(fd.attrib & _A_HIDDEN) { cout << "发现隐藏文件!" << endl; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值