C語言指針轉換為intptr_t類型
1、前言
今天在看代碼時,發現將之一個指針賦值給一個intptr_t類型的變量。由于之前沒有見過intptr_t這樣數據類型,憑感覺認為intptr_t是int類型的指針。感覺很奇怪,為何要將一個指針這樣做呢?如是果斷上網查查,發現我的感覺是錯誤的,所以,任何事情不能憑感覺,要弄清楚來龍去脈。先總結一下intptr_t類型,然后介紹指針與intptr_t類型的轉換,最后給出測試程序。
2、intptr_t類型
我接觸最早的處理器是32位,目前64位處理器發展迅速。數據類型特別是int相關的類型在不同位數機器的平臺下長度不同。C99標準并不規定具體數據類型的長度大小。
位數 | char | short | int | long | 指針 |
16 | ?1個字節8位 | ? 2個字節16位 | ?2個字節16位 | ?4個字節32位 | 2個字節16位 |
32 | ?1個字節8位 | ? 2個字節16位 | 4個字節32位 | ?4個字節32位 | 4個字節32位 |
64 | ?1個字節8位 | ? 2個字節16位 | ?4個字節32位 | ?8個字節64位 | 8個字節64位 |
為了保證平臺的通用性,程序中盡量不要使用long類型。可以使用固定大小的數據類型宏定義,這些宏定義需要引用stdint.h頭文件。
1 /* There is some amount of overlap with <sys/types.h> as known by inet code */2 #ifndef __int8_t_defined3 # define __int8_t_defined4 typedef signed char int8_t;5 typedef short int int16_t;6 typedef int int32_t;7 # if __WORDSIZE == 648 typedef long int int64_t;9 # else 10 __extension__ 11 typedef long long int int64_t; 12 # endif 13 #endif 14 15 /* Unsigned. */ 16 typedef unsigned char uint8_t; 17 typedef unsigned short int uint16_t; 18 #ifndef __uint32_t_defined 19 typedef unsigned int uint32_t; 20 # define __uint32_t_defined 21 #endif 22 #if __WORDSIZE == 64 23 typedef unsigned long int uint64_t; 24 #else 25 __extension__ 26 typedef unsigned long long int uint64_t; 27 #endif
關于intptr_t的類型定義如下:
?
//intptr_t類型是為指針準備的
1 /* Types for `void *' pointers. */2 #if __WORDSIZE == 643 # ifndef __intptr_t_defined4 typedef long int intptr_t;5 # define __intptr_t_defined6 # endif7 typedef unsigned long int uintptr_t;8 #else9 # ifndef __intptr_t_defined 10 typedef int intptr_t; 11 # define __intptr_t_defined 12 # endif 13 typedef unsigned int uintptr_t; 14 #endif
從定義可以看出,intptr_t在不同的平臺是不一樣的,始終與地址位數相同,因此用來存放地址,即地址。
3、指針與intptr_t
C語言指針用來保存變量或常量的地址,地址由處理器的位數決定。在windows程序中,經常用到句柄,其實就是一個地址,具備通用性,對底層進行了封裝。先對這個理解不深刻,什么時候需要將指針轉換為intptr_t類型。
4、測試程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#define ID_STR_LEN?? 12
#define NAME_STR_LEN 10
typedef struct student
{
??? char id[ID_STR_LEN];
??? char name[NAME_STR_LEN];
??? uint8_t age;
}student;
student * create_student()
{
??? student *stu = (student *)malloc(sizeof(student));
??? if (stu == NULL)
??? return NULL;
??? memset(stu, 0, sizeof(student));
??? return stu;
}
void *free_student(student *stu)
{
??? if (stu)
??? free(stu);
}
static void init_student(student * stu)
{
??? assert(stu);
??? const char *id = "2013112210";
??? const char *name = "Anker";
??? uint8_t age = 21;
??? memcpy(stu->id, id, strlen(id));
??? memcpy(stu->name, name, strlen(name));
??? stu->age = age;
}
static int handle_student(intptr_t handle)
{
??? if (handle == 0)
??? {
??? return -1;
??? }
??? student *stu = (student*)handle;
??? printf("id: %s\n", stu->id);
??? printf("name: %s\n", stu->name);
??? printf("age: %u\n", stu->age);
??? return 0;
}
int main()
{
??? student *stu;
??? stu = create_student();
??? init_student(stu);
??? //將指針轉換為intptr_t類型
??? intptr_t handle = (intptr_t)stu;
??? handle_student(handle);
??? free_student(stu);
??? return 0;
}