2016-01-24 202 views
3

有人可以向我解釋爲什麼這不起作用。我是java開發人員和新的c/c + +
據我瞭解數組指針實際上是數組第一個元素的指針,是否正確?c - 遞增數組指針

void test(char *tmp) 
{ 
    test2(tmp); 
    //*tmp++ = '1'; 
    //*tmp++ = '2'; 
    *tmp++ = '3'; 
    *tmp++ = '4'; 
    *tmp = 0; 
} 

void test2(char *tmp) 
{ 
    *tmp++ = '1'; 
    *tmp++ = '2'; 
} 

int main(int argc, char **argv) 
{ 
    char tmp[5]; 
    test(tmp); 
    printf("%s", tmp); 
    return 0; 
} 

只有34被打印。當我在函數test2中調試此代碼時tmp的指針在調用test2後增加1但函數test後,tmp的指針返回到其初始值。
如果我只是把所有的代碼在單一功能這樣的,它的工作原理:

void test(char *tmp) 
{ 
    *tmp++ = '1'; 
    *tmp++ = '2'; 
    *tmp++ = '3'; 
    *tmp++ = '4'; 
    *tmp = 0; 
} 

而且什麼就上線了*tmp = 0做。我從其他代碼複製它。沒有它,陣列末尾會有一些垃圾。

+2

1.字符串空終止(因此'* tmp = 0')。 2.通過使用'tmp [0] ='使代碼可讀。等 –

+0

@Ed癒合這是有效的,這是我嘗試的第一件事,但我不想'test'依賴'test2'。例如,如果我在'test2'中增加tmp 3次,我想在測試中繼續前進。那可能嗎? – pedja

+0

@dasblinkenlight固定 – pedja

回答

1

函數參數是它的局部變量。參數通過值傳遞給函數,這意味着傳遞參數的副本。

因此在函數test2中使用函數test的指針tmp的副本。對象副本的任何更改都不會影響對象本身。

test2的的呼叫可以設想以下方式

void test(char *tmp) 
{ 
// test2(tmp); 
    char *new_ptr = tmp; 
    test2(new_ptr); 
// ... 
} 

void test2(/*char *tmp*/) 
{ 
    char *tmp = new_ptr; 
    *tmp++ = '1'; 
    *tmp++ = '2'; 
} 

如果你宣佈test2的參數作爲參考指針,然後在這種情況下,指針本身可以改變。例如

void test(char *tmp) 
{ 
    test2(&tmp); 
    //  ^^^^ 
    //*tmp++ = '1'; 
    //*tmp++ = '2'; 
    *tmp++ = '3'; 
    *tmp++ = '4'; 
    *tmp = 0; 
} 

void test2(char **tmp) 
//   ^^^^^^^^^^ 
{ 
    *(*tmp)++ = '1'; 
    *(*tmp)++ = '2'; 
} 

至於陣列然後使用陣列在操作者在sizeof表達式中使用除了極少數例外,例如陣列被隱式轉換爲指針到它的第一元件。

所以,如果,例如,你有類型的數組T

T a[N]; 

然後下面的聲明

T *p = a; 

是有效的,指針由所述陣列的所述第一元素的地址初始化a

又如

char *s = "Hello"; 

這裏是字符串文字"Hello"在作爲初始化表達式中被使用。包含終止零'\0'的字符串文字將char[6]類型隱式轉換爲指向其第一個字符'H'的指針。

在C++中,字符串文字具有常量字符數組的類型。所以C++中的字符串文字"Hello"的類型爲const char[6]

所以在C++中,你必須寫

const char *s = "Hello"; 

但在兩種語言字符串文字是不可變的。

2

增加test2()中的'tmp'不會增加test()中的'tmp'。 test2()調用返回後,由test2寫入的'1'和'2'將被'3'和'4'覆蓋。

零是'\ 0'c風格'字符串'終止符。

+0

所以我怎麼能沒有明確指定數組索引?例如'tmp [0]','tmp [1]'等。 – pedja

+2

一種方法是從test2()返回指針:'char * test2(char * tmp)',.....'return tmp; 「並從temp中將其稱爲:'tmp = test2(tmp);' –

4

在功能test2,傳遞的指針意味着你可以修改什麼tmp點,但test2不修改指針本身

void test2(char *tmp) 
{ 
    *tmp++ = '1'; 
    *tmp++ = '2'; 
} 

所以在調用函數test,調用test2後指針不通過2個位置向前移動你所期望的,而不是tmp保持不變(這是指向數組的第一個值)。所以實際發生的是test2爲前兩個元素分配12,然後test34覆蓋這兩個值。

void test(char *tmp) 
{ 
    test2(tmp); 
    *tmp++ = '3'; 
    *tmp++ = '4'; 
    *tmp = 0; 
} 

而且什麼是*在最後一行TMP = 0做。

這是字符串終止符。

+0

好吧,我明白現在,但我怎麼能使它像這樣工作,而不使用'tmp [0]','tmp [1]'等 – pedja

0

這是正常的,如果你寫1中的所有函數你得到1234,但如果你寫2函數總是傳遞相同的指針,第二個覆蓋第一個已經完成的東西。

test: 
tmp -> Point to [100] 
call test2 giving [100] as parameter 
write 3 in [100] 
increment pointer from [100] to [101] 
write 4 in [101] 
increment pointer from [101] to [102] 

test2: 
tmp -> Point to [100] 
write 1 in [100] 
increment pointer from [100] to [101] 
write 2 in [101] 
increment pointer from [101] to [102] 

現在我想象你可以看到錯誤。

1

0是一個nul終止符,字符串以0或nul字節結尾,所以像printf()這樣的函數知道字符串結束的位置,因爲 - 一段字符串有多長?

由於您將指針傳遞給test2(),並且test2()正在遞增指針 - 但實際上並未將已更改/遞增的指針傳遞迴調用函數......就test()而言,指針沒有改變,所以後面的改變覆蓋了以前的改變。

#include <stdio.h> 
#include <stdlib.h> 

char *test2(char *tmp) 
{ 
    *tmp++ = '1'; 
    *tmp++ = '2'; 

    return tmp; 
} 

void test(char *tmp) 
{ 
    tmp = test2(tmp); 

    //*tmp++ = '1'; 
    //*tmp++ = '2'; 
    *tmp++ = '3'; 
    *tmp++ = '4'; 
    *tmp = 0; 
} 

int main(int argc, char **argv) 
{ 
    char tmp[5]; 

    test(tmp); 
    printf("%s", tmp); 

    return 0; 
} 

在這裏,test2正在向調用者返回已更改/增加的指針,tess()將接收已更新的char。由於您最後添加了0或nul字節,因此您需要至少5個元素的數組。

上面的代碼應該適合你。