簡體   English   中英

奇怪的聲明和C中函數的定義

[英]Weird declaration and definition of a function in C

我維護了一個非常古老的C項目(編寫這些項目的程序員已經很久了)我找到了類似這樣的東西:

(以//開頭的行給出包含以下行的文件的名稱。)

聲明:

// db/stor_procs/sp_table.c
/* Special hack prototype */
int32_t put_column_value(table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v);

// db/triggers/specials.c
/* BAD HACK */
int32_t put_column_value(table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v);

// db_sean_add_alarm/src/rt_access.c
int32_t put_column_value(struct xput_info *xptr, table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v);

// db_sean_add_alarm/stor_procs/sp_table.c
/* Special hack prototype */
int32_t put_column_value(table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v);

定義:

// db/src/rt_access.c
int32_t
put_column_value(struct xput_info *xptr, table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v){//....}

// db_sean_add_alarm/src/rt_access.c
int32_t
put_column_value(struct xput_info *xptr, table_t * tab, row_t * row, u_int16_t colnum, rt_value_t * v){//.....}

程序員從不在頭文件中聲明put_column_value ,但僅在.c文件中給出定義。 更奇怪的是,我找不到任何table_t *作為第一個參數的put_column_value定義,而且我100%確定table_tstruct xput_info是不同的類型(結構)。

但這不是整個故事。 最奇怪的部分是我可以在其他.c文件中找到put_column_value聲明。 現在我需要清理代碼,但我無法理解如何處理這種C魔法。 原始程序員在這里使用的“魔法”(hack)是什么?

整個項目有點大,我已經盡力簡化問題了。 請告訴我您是否需要任何其他信息來解決此問題。

編輯

找出原因,這個項目鏈接到其他庫,並且該庫有函數原型的定義,這就是為什么這個“魔術”(hack)可以找到實現。 現在來解決一個大問題 - 這個項目沒有堅實的單元測試,很難為它開發一個,沒有測試我不能改變代碼,不改變代碼我不能做單元測試^ _ ^。 啊,保持遺留代碼總是不是一件令人愉快的事情。

你有幾件事需要擔心。

  1. 令人震驚的編程風格,將原型放在源代碼而不是頭文件中。 修復這很容易(但很繁瑣)。
  2. 聲明和定義之間的不匹配。 假設原型中有不同數量的參數和函數的兩個定義。 似乎這些原型實際上並沒有被使用,因為如果它們是程序會崩潰(假設實際代碼沒有做一些真正令人厭惡的論點)。 所以你可能有機會做一些清理工作。
  3. 您有兩個put_column_value實現。 據推測,這些應該存在於不應該一起使用的不同庫中。 它看起來像這些目錄中的一個包含一個新版本的庫與某種警報,但我只是從名稱猜測。

所以你困惑的第一部分是聲明和定義之間的不匹配。

對於構建過程,只要沒有編譯單元看到它們兩者就可以。 但該計划在這個地方不起作用,是嗎?

第二部分,關於將聲明放入其他.c文件,是非常糟糕的風格。 它應該 - 如果有的話 - 只在調試期間使用,我暫時需要在另一個文件中使用一個函數。

你可以通過將(正確的)聲明放入一個頭文件來解決這兩個問題,你需要將它包括在內,以及 - 為了檢測不匹配 - 從你聲明的位置開始。

哎喲! 我的猜測是,之前的程序員需要在一個地方為put_column_value添加一個參數, put_column_value在任何地方都懶得去做。 他也有可能在實現的中途並且意圖修復其他文件,但在作業完成之前退出。

您應該查看鏈接器命令以查看哪個定義實際與程序鏈接。

您還應該檢查是否從具有錯誤聲明的文件中調用了put_column_value (在運行時)。 由於額外的參數是第一個放置的,所以使用faulty聲明的調用仍然可以工作,只要實現在這些實例中實際上不使用新參數(如果它寫入它,它將破壞堆棧)。 因此“魔術黑客”。 它打破了C標准,在技術上導致了不確定的行為。

我的建議是,您要么在任何地方修復呼叫,要么將該功能吐成兩部分,並重命名其中一部分。 在任何一種情況下,您都應該將聲明移回頭文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM