2014-10-04 53 views
2

我試圖通過編寫我自己的函數來模仿strcpy的工作方式。我的問題更具體到數組的大小。C字符串副本,數組的大小

我想要的stringA內容複製到stringB,我已經聲明爲1.

  1. 大小不應該我得到一個錯誤說stringB是太小,無法容納stringA?原因,我懷疑我沒有得到一個錯誤是因爲一個數組名稱StringB被轉換爲一個指針?

  2. 爲什麼char str[1] = "abcd"非法呢?

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    
    void strCopy(char *source,char *destination) { 
        printf("%p,%p\n",source,destination); 
        while (*source != '\0') { 
         *destination = *source; 
         printf("> %c,%p,%p\n",*source,source,destination); 
         source++; 
         destination++; 
        } 
    
        *destination = '\0'; 
    } 
    
    int main(int argc,char *argv[]) { 
        char stringA[] = "To be or not to be."; 
        char stringB[1]; 
        strCopy(stringA,stringB); 
        printf("StringB: %s\n",stringB); 
    
        return (0); 
    } 
    
+0

這不是語言的工作原理。你可以(也可以)自由地在腳下射擊自己,並且會產生一個*形式不良的*程序。它執行*未定義的行爲*,並且對於任何定義的**沒有任何**期望(*混沌*不能抵抗的鬆散「定義」)是合理的。 – WhozCraig 2014-10-04 12:37:35

+0

使用'valgrind'。然後你會看到你正在做一件壞事。 – skywall 2014-10-04 12:49:36

+0

謝謝,我需要使用valgrind的memcheck功能嗎? – hmmm 2014-10-05 18:03:06

回答

2

1)我不應該得到一個錯誤說stringB是太小,無法容納stringA?

由於編譯器內存分配方案,您沒有收到任何錯誤。編譯器很有可能在之後將內存分配給stringB first和stringA。因此考慮一下,如果stringB的內存位置是1000(只有一個字節),那麼stringA的內存位置將從1001到1020(包括空值)。所以當你試圖從stringA複製內容到stringB到你的函數時,它實際上是從位置1001複製到1000,然後從1002複製到1001等等,所以根據你的程序你必須有如圖所示的輸出,如果是這種情況。看來你正在打印字符串的地址。看到字符串的地址並檢查是否是這種情況。再次,這只是string2首先比stringA分配內存的結果。在編譯器的所有變種中,每次都是這樣的答案並不是必須的。

stringB:是或不是蜜蜂

stringA:○是或不是蜂

現在因爲兩個陣列存在於堆棧幀並且兩者都通過指針訪問你沒有得到錯誤,所以當使用指針完成數據複製時,編譯器不關心數組的大小。它只是複製,直到你在允許的內存空間。如果情況並非如此,並且stringA將首先出現在內存中,那麼您會得到分段錯誤。

2)爲什麼char str [1] =「abcd」非法呢?

這不是你的情況非常不同的情況,你只給字符串分配一個字節,並用比它的大小更多的字符對它進行初始化。注意你的數據拷貝是在運行時完成的,但是這個初始化是在編譯時進行的,所以編譯器知道數組的大小並且會給你一個警告,這不是非法的,但是編譯器只把第一個字符賦值給字符串,你可能會得到不可預知的結果是最後沒有剩餘空字符。

+0

輸出我得到的是: StringB:生存還是毀滅 StringA:○是或不被 。我看了一下從stringA地址和「T」被從StringB「O」覆蓋。 爲什麼編譯器會先爲stringB分配內存,爲什麼不用stringA?非常感謝。 – hmmm 2014-10-04 22:44:52

+0

知道兩個字符串的位置後,它可以更清楚。在評論中發佈位置和輸出。 – 2014-10-04 22:46:47

+0

> T,0x7fff6f334d70,0x7fff6f334d6f > O,0x7fff6f334d71,0x7fff6f334d70 >,0x7fff6f334d72,0x7fff6f334d71 > B,0x7fff6f334d73,0x7fff6f334d72 > E,0x7fff6f334d74,0x7fff6f334d73 >,0x7fff6f334d75,0x7fff6f334d74 > O,0x7fff6f334d76,0x7fff6f334d75 >ř ,0x7fff6f334d77,0x7fff6f334d76 >,0x7fff6f334d78,0x7fff6f334d77 #輸出截斷## A的 地址:B的0x7fff6f334d70 地址:0x7fff6f334d6f 我看到B被提前分配的內存,只是不知道什麼編譯器的原因去做這個。 – hmmm 2014-10-04 22:54:34

1

1)我不應該得到一個錯誤說stringB是太小,無法容納stringA?

根據內存空間stringB的放置位置,您可能不會收到錯誤。如果stringB指針位於應用程序內存的中間,那麼您肯定可以將值寫入超出其聲明邊界的值。你只會覆蓋用來存儲其他值或函數的內存。 C/C++從不檢查是否像其他語言一樣經過了數組長度,例如Java的。

2)爲什麼char str 1 =「abcd」非法呢?

由於您的程序的行爲根據您的實施完全未定義,因此很難準確描述發生了什麼。

另請參閱以下職位:why doesn't my program crash when I write past the end of an array?