#include <stdio.h>
#include <string.h>
typedef struct {
char name[20];
long id;
long long salary;
} Personal1;
typedef struct {
char *name;
long id;
long long salary;
} Personal2;
Personal1 p1={"Charlie", 1l, 45000l};
Personal2 p2={"Richard", 2l, 45000l};
int main(void)
{
printf("name:%s id:%ld salary:%ld\n", p1.name, p1.id, p1.salary);
printf("name:%s id:%ld salary:%ld\n", p2.name, p2.id, p2.salary);
strcpy(p1.name, "test1");
//strcpy(p2.name, "test2"); //這行可以compiler過,不過程式執行會當在這
printf("name:%s id:%ld salary:%ld\n", p1.name, p1.id, p1.salary);
printf("name:%s id:%ld salary:%ld\n", p2.name, p2.id, p2.salary);
return 0;
}
首先,這程式有個錯誤的理解,就是在宣告p1.p2同時填入struct裡的內容時,p2的填入過程會填錯...意思是name.id及salary會互相覆蓋之類的...
不過結果不會也,compiler會很聰明的配置一塊區域,給name,然後指向它,其它就正確的填入應該的位置...
接下來又發生一個問題,就是註解掉的那一行,雖然可以編譯通過,不過執行時,會發生Access violation的錯誤....
猜測,這代表編譯器會配置空間放字串,不過是放在唯讀區域
另外又讓我弄了一個實驗,程式如下:
#include <stdio.h>
char test1[]="Charlie";
char *test2="Richard";
int main(void)
{
printf("%s\n",test1);
printf("%s\n",test2);
strcpy(test1,"test1");
//strcpy(test2,"test2"); //這行可以compiler過,不過程式執行會當在這
printf("%s\n",test1);
printf("%s\n",test2);
return 0;
}
現在我們知道,這兩種預宣告字串內容的方法,對於compiler配置的方法是不同的...
char test1[]="Charlie"; 配置剛好的記憶體空間,並且從literal constant區域複製字串內容過來,而test1只是個常數,代表這個配置空間的第一個位置
char *test2="Richard"; 配置一個指標變數,並且複製literal constant區域內某字串的第一個位置值,所以*test2指向literal constant這個區域,由於唯讀,所以對其修改會產生Access violuation....
另外這些區域的保護作用,也不是編譯器說了算,是要OS(認出來做處裡)和CPU(的機制)互相配合,才可以實現....
若是某些embedded system的情境下,有可能是literal constant的區域(section)是放在唯讀記憶體(或flash),所以無法寫入,或者寫也寫不進,如果經過適當的處理(Relocate 和適當的搬移),把literal constant區域複製到RAM上,則存取就沒問題了
相關連結:
http://twpug.net/docs/ccfaq/node16.html#q:1.32
http://www.yuanma.org/data/2007/0305/article_2375.htm
http://birdegg.wordpress.com/2006/10/21/re-問題-cc中char與char的差異/
沒有留言:
張貼留言