C語言指標轉換為intptr_t型別
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_defined 3 # define __int8_t_defined 4 typedef signed char int8_t; 5 typedef short int int16_t; 6 typedef int int32_t; 7 # if __WORDSIZE == 64 8 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 == 64 3 # ifndef __intptr_t_defined 4 typedef long int intptr_t; 5 # define __intptr_t_defined 6 # endif 7 typedef unsigned long int uintptr_t; 8 #else 9 # 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;
}