2013-12-17 31 views
1

「高級編程UNIX環境,第三版」,第151頁:如何將「有副作用的表達式」傳遞給getc?

getcfgetc之間的區別是getc可以實現 宏,而fgetc不能作爲宏來實現。這意味着 三件事:

  • getc的參數不應該副作用的表達式。
  • 由於fgetc保證是一個函數,我們可以採取它的地址。這允許我們將fgetc的地址作爲參數傳遞給另一個 函數。
  • 撥打電話fgetc可能比撥打getc需要更長的時間,因爲通常需要更多時間來調用某個功能。

什麼「副作用表達」可以發生用於與流指針作爲參數函數簽名?

#include<stdio.h> 
int getc(FILE* stream); 
int fgetc(FILE* stream); 
+4

例如'CH = GETC(filePointerArray [++ I])'' – BLUEPIXY

+0

GETC(FOO())'其中'FILE * foo的(){/ *副作用* /}'。 'getc(strptr ++)'其中'FILE * strptr'。 'getc(* pstrptr ++)'其中'FILE ** pstrptr'。等等。拿出例子很容易。 –

+0

謝謝,BLUEPIXY,Jim Balter。 –

回答

6

可能有數以百計的方式來傳遞一個具有副作用的表達,而是一個「可信的」一會是這樣的:

FILE *files[NUM_FILES]; 
... 
int rc = getc(files[counter++]); 

如果getc甚少實現爲宏,表達files[counter++]可能會被多次評估,導致意外行爲。

+2

「很差」? 「我懷疑任何理智的C庫」?你不知道你在說什麼。原始的stdio庫和它的許多後代實現了getc(f),就像' - (f) - > ptr < (f)->結束了嗎? *(f) - > ptr ++:__getc(f)'表示速度,這就是getc被允許成爲一個重新評估其參數的宏的原因。 –

+0

-1 re @JimBalter關於「如果getc作爲宏實現得不好,表達式文件[counter ++]可能會被多次計算,導致意外的行爲。我懷疑任何理智的C庫都會出現這樣的錯誤。 」。這是危險的消息傳遞。 –

+0

使那個' - (f) - > cnt> 0? *(f) - > ptr ++:__getc(f)' –

1

作爲一個例子,不寫

FILE* foo() { puts("Bah!\n"); return stdout; } 

void advance() { getc(foo()); } 
+0

此代碼適用於我。錯誤不會發生。 –

+0

@Bush:沒有保證=故障的可能性,不能保證有故障 –

+0

@Bush您的回答如何?您問過如何將具有副作用的表達式傳遞給getc,這顯然是一個例子。你引用的文字說「getc可以實現爲一個宏」 - 我意識到英語不是你的母語,但你肯定明白「可以」意味着什麼?如果你打電話進來,沒有超過一個「巴」!打印,那麼你使用的getc版本不是宏。 (您可以通過查看stdio.h或宏擴展您的源代碼來進行檢查,例如,使用gcc -E) –

相關問題