2017-10-28 70 views
-3
#include <stdio.h> 
#include <string.h> 

char lists[10][25]; 
char name[10]; 

void main() 
{ 
    scanf("%s" , lists[0]); 
    memcpy(name , lists[0], 25); 

    printf("%s\n" , name); 
} 

在上面的代碼我預定義的字符數組「名」的大小爲10。 現在,當我給輸入爲:有關memcpy函數如何運行的說明?

輸入 - abcdefghijklmnopqrstuvwxy

我得到的輸出是相同的字符串:abcdefghijklmnopqrstuvwxy

應該不會輸出爲:abcdefghij?

即使陣列的大小限制爲10,這將如何變得可能?

+3

這是一個* undefined behavior *的例子,這意味着可能發生任何事情。包括程序正常工作。 – klutt

+1

你的代碼在線以外着色,非常基本的UB。如果你想讓它炸燬並重新格式化磁盤,那麼你需要更多的顏色。交換這兩個變量聲明是值得一試的。 –

+1

大多數語言都會阻止程序員寫入數組的末尾。 C沒有。這是你的責任。 – jarmod

回答

1

因爲它不知道它正在寫入的已分配內存的大小,所以你就不知道寫入額外數據的位置了。您可能不在其他平臺上,或使用不同的編譯器或不同的優化設置。

當將size參數傳遞給memcpy()時,最好考慮目標存儲器的大小。

使用字符數組時,如果想要更安全地關於不超限內存,可以使用strncpy()。它會照顧在正確的地方插入尾隨NULL

+0

所以,你的意思是說如果我可用的內存塊是10,那麼這將不會發生? – Jamzy

+1

不,如果內存是25,那麼你沒有問題。 C取決於程序員對內存分配和寫入等方面的注意。 – Steve

+0

我的意思是說可用的物理內存只有10個,那麼我將無法找到一些額外的內存,然後它會提出一個錯誤或什麼!對 ?? – Jamzy

0

首先,數組是指針。在C中,沒有像Java那樣的長度檢查。

當您編寫char a[2];時,操作系統會爲您提供2個字符的內存空間。 例如,讓存儲器是

|1|2|3|4|5|6|7|8|9|10|11|12| 
a 

a是指向的地址1。a[0] = 0;*(a+0) = 0相等,這意味着write 0 to the address a + offset 0

因此,如果您嘗試寫入未分配的地址,可能會發生意想不到的情況。

例如,讓我們說我們有char a[2];char b[2];和存儲器映射

|1|2|3|4|5|6|7|8|9|10|11|12| 
a b 

然後a[2] = 0等於b[0] = 0。但是如果這個地址是另一個程序的地址,那麼會出現分段錯誤。

嘗試程序(它可能沒有編譯器的優化工作):

#include <stdio.h> 
#include <string.h> 

char a[4]; 
char b[4]; 

void main() 
{ 
    scanf("%s" , a); // input "12345678" 
    printf("%s\n" , b); // print  "5678" 
} 

memcpy剛剛從一個地址複製到其他的數據你說的大小。

在你的例子中,你是luky,因爲你訪問的所有地址分配給你的程序(在你的內存頁面內)。

在C/C++中,您有責任正確處理內存。另外,請記住,字符串以char \0結尾,因此在數組內我們通常有9個字符和\0

+1

我認爲你在這裏有一個錯字:「a [0] = 0;與*(a + 1)= 0相等,意思是寫0到地址a +偏移量0。 – MFisherKDX

+0

當然可以。謝謝。 (現在正確) – GramThanos

+0

「| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ab然後a [2] = 0等於b [0] = 0 「。如果你依靠這種行爲,你就會受到傷害。不知道編譯器/優化器可能做什麼。 – MFisherKDX