2013-05-13 93 views
1

我有一種情況,我在內存中有一個大字符串,我想用這些函數的切片(例如,給我一個從30開始的14個字符運行)。爲了做到這一點,我不得不讓消費者使用雙指針作爲緩衝區。然而,如果我查看像pread或strcpy這樣的各種庫函數,它們只接受一個指針級別的字符串緩衝區。針對緩衝區的指針與雙指針

他們是怎麼做到的?看起來他們應該也需要一個雙指針,以同樣的方式改變「在另一邊」的值。

+0

「看起來他們應該還需要一個雙指針以更改值」 - 不。一個間接級別就足夠了,他們不改變指針,只改變指針的值指針。 – 2013-05-13 14:22:44

+0

當您將'* bar'設置爲'&tmp [1]'時,您將它指向一個基於堆棧的自動變量,當_foo_返回時它將超出範圍。你想解決這個問題嗎? – 2013-05-13 14:30:25

+0

這是示例代碼。這是真正的代碼堆中的一個多兆字節的二進制塊。 – codepoet 2013-05-13 14:37:46

回答

6

大多數這樣的函數不會改變指針,它們會改變內存。的strcpy()原型爲:

char * strcpy(char *dest, const char *source); 

這意味着存儲器指向由dest將與內容從source被覆蓋,直到(且包括)第一個0字符被發現。

調用者將調用這個緩衝區的地址將被修改。

對於你的情況,聽起來好像你在零拷貝字符串切片,那麼使用指針指針更有意義。請注意,終止將成爲一個問題,但不能複製C字符串而不需要複製,否則原始文件將被切片。

你當然可以定義一個字符串拷貝切割功能:

char * slice_string(char *dest, size_t dest_max, 
        const char *source, int start_index, int end_index); 

這將從source字符複製到dest,就像strcpy(),但只複製子串。我做了索引簽名,以便您可以支持負面索引例如Python。

請注意,該函數不被稱爲strslice(),因爲該函數名稱是保留的。

+0

+1提到保留名稱問題 – 2013-05-13 15:12:30

3

pread()strcpy()不改變指針指向的地方;他們更改緩衝區包含的內容。因此,他們不需要雙指針表示法。

你很可能做到最好:

const char *foo(void); 

這就避免了雙指針,並允許你寫:

char *baz = foo(); 

在你的榜樣主程序。

表示字符串切片沒有空終止將需要一些照顧(開始位置和長度)。也許你會用一個指針和長度的結構,在這種情況下,你可以將一個指向這個結構的指針傳遞給你的函數,或者返回一個結構的副本。

2

您需要區分指針和指針。考慮一個函數採取這樣調用一個單級指針:

char *p = ...; 
f(p); 

f接收的p副本。此副本指向相同的內存p呢,所以f可以在內存p點,改變價值觀,但它可以變化其中一塊內存p點。在合同,接受了雙指針的函數被調用是這樣的:

char *p; 
g(&p); 

g將能夠做的一切f可以做,使用*the_parameter(其中給出了p值)。但此外,它可以改變p,所以它可以使p指向一些不同的內存塊。對於大多數功能來說,這不是必需的,但它有時很有用。