2011-05-23 36 views
2

下面是一個程序的功能:字符串連接到另一個沒有分配,這是爲什麼?

//read the specified file and check for the input ssn 
int readfile(FILE *fptr, PERSON **rptr){ 
    int v=0, i, j; 
    char n2[MAXS+1], b[1]=" "; 

    for(i=0; i<MAXR; i++){ 
     j=i; 
     if(fscanf(fptr, "%c\n%d\n%19s %19s\n%d\n%19s\n%d\n%19s\n%19s\n%d\n%d\n%19s\n\n", 
        &rptr[j]->gender, &rptr[j]->ssn, rptr[j]->name, n2, &rptr[j]->age, 
        rptr[j]->job, &rptr[j]->income, rptr[j]->major, rptr[j]->minor, 
        &rptr[j]->height, &rptr[j]->weight, rptr[j]->religion)==EOF) { 
      i=MAXR; 
     } 
     strcat(rptr[j]->name, b); 
     //strcat(rptr[j]->name, n2); 
     if(&rptr[MAXR]->ssn==&rptr[j]->ssn) 
      v=j; 
    } 
    return v; 
} 

的註釋行就是這樣,因爲某些原因,陣列「B」包含字符串「N2」儘管一個明顯缺乏分配。這發生在第一次strcat調用之前,但在fscanf調用之後。

它確實達到了預期的目標,但是爲什麼n2連接到b的末尾,特別是當b僅爲1個數組元素保留空間時?

下面是變量定義的的fscanf呼叫後一個片段:

*rptr[j]->name = "Rob" 

b = " Low" 

n2= "Low" 
+0

b不是空終止......它只有一個字符的空間......空間......它可能有東西在裏面,因爲你溢出了一個緩衝區。 – forsvarir 2011-05-23 14:13:04

回答

3

它有效,因爲你很幸運。 bn2碰巧在內存中以正確的順序彼此相鄰。 C不會對數組進行邊界檢查,並且會很高興地讓你溢出。所以,你可以聲明一個這樣的數組:

char someArray[1] = "lots and lots of characters"; 

C編譯器(當然舊的)會認爲這是好的,即使顯然不是在someArray足夠的空間來存儲多個字符。我不確定它是否定義了在這種情況下它會做什麼(我懷疑不是),但是在我的編譯器中它將總體限制爲數組的大小,所以它不會溢出邊界(someArray=={'l'})。

你的情況是一樣的(儘管不太極端)。 char b[1]正在創建一個有足夠空間存儲1個字節的數組。你在這個字節中放了一個空格,所以沒有空終止符。它會一直拷貝內存直到它到達一個空終止符,因此它會一直繼續下去,直到它找到一個,即使它不是直到下一個字符串的末尾(這就是你的情況發生了什麼)。

如果您已經使用C++編譯器,它會拋出至少一個警告(或更可能是錯誤的),告訴你,你想放太多的物品入陣。

+0

+1,雖然我不會稱之爲獲取「幸運」,因爲它不會徹底炸燬,並讓你知道有一個明顯的問題。該行爲未定義爲每6.7.8/2:「沒有初始化程序將嘗試爲未包含在被初始化的實體中的對象提供值」 – 2011-05-23 15:05:10

+0

@John Bode:是的,我是幸運50:50自己...謝謝供參考:) – forsvarir 2011-05-23 15:08:09

2

B需要是大小爲2,1的空間中,1空。

+0

換句話說,'b [1] =「」;'等同於'b [1] = {'','\ 0'};' – Lundin 2011-05-23 14:21:40

+0

@Lundin:No,'b [1] =「」; '相當於'b [1] = {''};'。 'b [2] =「」;'相當於'b [2] = {'',0};'... – forsvarir 2011-05-23 14:24:27

+0

@forsvarir公平的,我只是想說明它爲什麼是一個錯誤。 – Lundin 2011-05-23 14:28:29

相關問題