在chinaunix論壇上有人問到關於變量存府類型的問題,我以爲能夠寫個測試代碼加深你們對內存使用和佈局的理解。下面我把原問題及處理辦法貼出來,限供你們參考。linux
原問題:佈局
static void testB (char *src) { /* 判斷傳入的src 是屬於 @1/2/3 ??? */ do_somthing (); } static void testA (char *src) { char *a = "hello world"; char b[100] = "hello world"; testB (a); /* @1 */ testB (b); /* @2 */ testB ("hello world" ); /* @3 */ }
@1 有名常量
@2 緩衝資源
@3 未名常量
怎麼用宏去區別啊???測試
下面是對這個問題的處理辦法:優化
編譯器和語言並無直觀的提供什麼功能去實現這個處理,能夠換個思路,在C中有四個存儲類型static,automatic,register,dynamic。每種類型的存儲的地址都是可識別的,經過對存儲地址的判斷能夠識別實事的變量或常量變型。
char *a = "hello world";testB (a); 和 testB ("hello world" ); 這兩個調用其實是同樣的。編譯器在處理的時候會把對hello world的變引指向相同的地方(編譯器基本都這麼進行優化處理,不屬於標準規定)。根據上述說法那下面的公式成立:編譯器對常量變量的內存處理策略+操 做系統的內存佈局=可明肯定位的內存識別。因爲操做系統的內存佈局因系統而定,編譯器的實現也各有不一樣,因此就算得出結論要實現相關處理的代碼也是很難進 行移植的。下面是完成相關功能的代碼在linux下測試經過。spa
#include <stdlib.h> #include <stdio.h> #include <string.h> int global_dummy = 0; static void testB (char *src) { /* 判斷傳入的src 是屬於 @1/2/3/4*/ int local_dummy = 0; if( (unsigned long)src < (unsigned long )&local_dummy ){ //if( src > testB ){ if( (unsigned long )src < (unsigned long )&global_dummy ){ printf("string literal\n\n"); } else if ( (unsigned long ) src > (unsigned long ) &global_dummy){ printf("malloc string\n\n"); } //} } else { printf("array: stack\n\n"); } } static void testA () { char *a = "hello world"; char b[100] = "hello world"; char *c = malloc(100); strcpy(c,a); printf("char *a = \"hello world\";\n"); testB (a); /* @1 */ printf("char b[100] = \"hello world\";\n"); testB (b); /* @2 */ printf(" (\"hello world\" )\n"); testB ("hello world" ); /* @3 */ printf("char *c = malloc(100);\n"); testB (c ); /* @4 */ free(c); } int main(int argc,const char** argv) { testA(); return 0; }
程序的運行結果以下:
char *a = "hello world";
string literal
char b[100] = "hello world";
array: stack
("hello world" )
string literal
char *c = malloc(100);
malloc string操作系統
雖然沒有處理和測試全部狀況,但以述代碼我以爲針對理解內存佈局和變量使用問題已經足夠了。unix
下面貼個linux下程序運行的內存佈局圖,能夠加深對上述代碼的理解code
ps:這不是抄襲,是原創blog