C語言的Struct Hack筆記_C 語言

來源:互聯網
上載者:User

最近在搞Compiler的CodeGenerator實驗,有一部分需要把Java程式翻譯成C程式,比如:

複製代碼 代碼如下:

int [] array;
array = new int[10];
System.out.println(array.length); //10

這段代碼翻譯成C很自然的想法是:
複製代碼 代碼如下:

int * array; // int array[] not support in C
array = (int*)malloc(sizof(int)*10);
printf("%d\n",sizof(array)/sizeof(int)); // 1

但很可惜這樣是錯誤的,因為malloc操作在堆上分配空間,不一定是連續的,sizof(array)得到的是指標本身所佔的單元,和sizeof(int)相等,無法通過sizof求得數組長度。它和下面還不一樣:
複製代碼 代碼如下:

int array[10];
printf("%d\n",sizof(array)/sizeof(int)); // 10

這裡array是數組,是指向整個連續儲存空間的常量,所以sizeof對其操作求得的是整個地區的長度。但是當數組名作為函數的參數傳遞時,數組就退化為指標,又回到了剛才問題。

我們應該怎麼做?

在 StackOverflow 搜了一下,發現ANSI C根本沒有直接辦法通過指向記憶體的指標求得分配長度。但Windows下提供了計算指標指向的記憶體大小的方法[malloc.h]:

_msize : returns the size (in bytes) as an unsigned integer.

複製代碼 代碼如下:

size_t _msize(
void *memblock
);


但由於作業系統策略的原因,實際分配到的大小可能會比指定的大一些.

在Linux下,指標往前位移一個整形大小的單元也會記錄實際分配的大小,我們來窺探一下那個單元的內容:

複製代碼 代碼如下:

//test.c
int main(){
 int * p;
 int i;
 int size;
 for (i=1;i<11;i++)
 printf("%d ",i);
 printf("\n");
 for (i=0;i<10;i++){
 p = (int*)malloc(sizeof(int)*i);
 size = *(int*)((char*)p-sizeof(int));
 printf("size:%d ",size);
 free(p);
 }
 printf("\n");
}


$gcc test.c
$./a.out
1  2  3  4  5  6  7  8  9  10
17 17 17 17 25 25 33 33 41 41


看來Linux的分配策略不能使得記憶體大小和元素個數一一對應,此法不可用。 後來發現在Linux下原來也有類似_msize的函數[malloc.h]:

複製代碼 代碼如下:

int * array;
int size;
array = (int*)malloc(sizof(50);
size = malloc_usable_size(array);
printf("%d\n",size);//50

但是malloc.h不屬於標準C,我們還要繼續尋找通用之法。經過大量查閱,終於發現了一種code trick,稱作struct-hack. 前面提到過,在C語言中,int a[]是違法的,但是把它作為struct的最後一個成員卻是可以的:

複製代碼 代碼如下:

typedef struct array{
 int size;
 int free;
 int buf[];
 }array,*Tiger_array;


這是在C語言的後期加入的特性,目的就是為了實現flexible array, 這樣每次給數組分配空間時,需要同步記錄size大小。而求size的時候,直接取出來即可:

複製代碼 代碼如下:

 Tiger_array ta;
ta = (int*)malloc(sizeof(array)+100);
ta->size = 100;
ta->free = 0;

需要注意一點,這時分配的大小應該是sizeof(struct)加上需求的數組大小。

這個問題就說到這裡。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.