我目前正在通過遵循 Brian 和 Dennis 的《The C Programming Language》一書來學習“指標”。
我編譯失敗:
#include <stdio.h>
void _strcpy(char *s, char *t)
{
while(*s = *t )
;
}
錯誤訊息是:
warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
while(*s = *t )
~~~~~^~~~~~
55.c:5:16: note: place parentheses around the assignment to silence this warning
while(*s = *t )
^
( )
55.c:5:16: note: use '==' to turn this assignment into an equality comparison
while(*s = *t )
^
==
1 warning generated.
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
在試圖找出導致錯誤的原因之后,我認為這可能是“越界”。
所以,我試著用這個來測驗我的假設:
int main(void)
{
char *t = "now is the time";
char *s, *string = s;
while(*s = *t );
printf("%s", string);
}
好吧,它仍然給了我上面相同的錯誤訊息:(
會不會是編譯器的問題?
我正在使用:
gcc -o [filename] [filename.c]
你能幫幫我嗎?
謝謝你,祝你有美好的一天!
uj5u.com熱心網友回復:
這不是錯誤,而是警告。
這樣的警告旨在捕獲如下邏輯錯誤:
int found=0;
while (found=0) {
// do something
if (abc) {
found = 1;
}
}
在應該使用相等比較時使用了賦值。
在您的情況下,分配是故意的。因此,您可以按照警告的建議進行操作,并在分配周圍放置一組額外的括號,讓編譯器知道您的意圖。
while ((*s = *t ))
uj5u.com熱心網友回復:
關于內部條件的分配:
K&R 是在 1970 年代撰寫的,因此遵循 1970 年代(完全缺乏)最佳實踐。這種strcpy從 K&R 實作的方式實際上變成了慣用的 C,盡管后來由于各種原因被認為是有問題的。
在 1980 年代,程式員開始意識到在內部使用賦值if或回圈條件是不好的做法。部分原因是它在控制陳述句中間引入了副作用,部分原因是程式員傾向于混淆=and ==(尤其是當時的 Pascal 程式員,因為 Pascal 使用:=and =)。
為了解決這個問題,出現了一些令人困惑的 1980 年代運動,宣傳使用“尤達條件”,即像虛構的尤達角色一樣使用“逆向語法”進行編程。那是if(0 == x)而不是if(x == 0)。
但是,這并不能解決將控制陳述句與一個或多個副作用混合的更嚴重的程式設計問題。此外,人們開始意識到編譯器可以很容易地警告if(x = 0). 因此,Turbo C 從 1989 年開始警告“可能的錯誤分配”,這是尤達條件的終結。
所有現代編譯器也都有這個警告,但現在提供了一種“事實上的標準”方法來避免警告,即使用雙括號:if((x = 0)). 這意味著“我實際上是故意在這里做作業”。因此,解決問題的快速而骯臟的方法是將代碼更改為:
while ((*s = *t ))
其他問題:
避免以下劃線開頭的識別符號,因為它們是為標準庫實作保留的。
將
運算子與其他運算子組合在同一個運算式中通常被認為比在條件內賦值更危險,因為它不僅會引入副作用,還會引入潛在的未排序的副作用,并且還會使代碼難以閱讀。在運算式中具有多個副作用通常不是一個好主意。
備擇方案:
您可以將代碼重寫為(更具可讀性)
void another_strcpy (char* s, char* t)
{
for(*s = *t; *s != '\0'; s , t )
{}
}
或者也許是(非常易讀)
void another_strcpy (char* s, char* t)
{
*s = *t;
while(*s != '\0')
{
s ;
t ;
*s = *t;
}
}
盡管就性能而言,所有這些實作(包括 K&R )都是幼稚的。正如生產質量標準庫中所見,高效的復制演算法適用于對齊的資料塊。
此外,理想情況下使用 const 正確性和指標別名優化:
void another_strcpy (char* restrict s, const char* restrict t)
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/480157.html
