Skip to content

Fix2compile#3

Open
alan23273850 wants to merge 6 commits intoguluchen:masterfrom
alan23273850:fix2compile
Open

Fix2compile#3
alan23273850 wants to merge 6 commits intoguluchen:masterfrom
alan23273850:fix2compile

Conversation

@alan23273850
Copy link
Copy Markdown

@alan23273850 alan23273850 commented Feb 11, 2026

保留 inline 且能成功編譯的修改說明

一、問題來源

專案中多個 header(vector.hbitvector.hboolformula.hcdnfformula.h)把函式宣告成 static inlineinline,但只有宣告、沒有定義;實際定義在對應的 .c 裡,且用 inline

在 C99 下:

  • 只有 inline、沒有 extern 的定義不會產生可供連結的外部符號。
  • 其他 .c 只看到 header 的宣告,編譯時無法 inline,連結時又找不到符號 → undefined reference

此外,header 被 C 與 C++ 共用(例如 cpp_examples);在 C++ 中 malloc 回傳 void*,不能隱式轉成其他指標型別,需顯式轉型。


二、目標

  1. 能編譯、連結:所有使用到這些函式的編譯單元都能正確連結。
  2. 保留 inline 效果:讓編譯器在每個 include 該 header 的 .c 裡都能 inline 這些小函式,而不是只在本檔或依賴 LTO。

三、作法總覽

採用 「在 header 裡用 static inline 並提供完整定義」 的方式,讓每個 include 該 header 的編譯單元都有一份定義,編譯器可以選擇 inline,且不會產生連結符號問題。

1. vector(vector.h / vector.c)

  • vector.h
    • 加上 #include <assert.h>
    • vector_lengthvector_getvector_setvector_add 改為 static inline 且在本檔內寫完整定義(含函式本體)。
  • vector.c
    • 刪除上述四個函式的定義,只保留 vector_newvector_freevector_resize 與內部 helper。

效果:任何 include vector.h 的 .c(含 cdnfformula、boolformula、cdnf、oracle 等)都能在編譯時 inline 這四個 accessor。


2. bitvector(bitvector.h / bitvector.c)

  • bitvector.h
    • 加上 #include <assert.h>
    • 在 header 內提供僅供 inline 使用的 macro:BITVECTOR_BITS_IN_INTbitvector_array_idx()bitvector_bit_pos()(避免與 .c 內部的 macro 衝突)。
    • bitvector_lengthbitvector_setbitvector_get 改為 static inline 且在本檔內寫完整定義
  • bitvector.c
    • 刪除上述三個函式的定義,保留其餘函式;內部仍用原本的 BITS_IN_INT / get_array_idx / get_bit_pos

效果:任何 include bitvector.h 的 .c 都能 inline 這三個 accessor。


3. boolformula(boolformula.h / boolformula.c)

  • boolformula.h
    • 加上:#include "type.h", "vector.h", <assert.h>, <stdlib.h>, <stdio.h>, <stdbool.h>(C 用)。
    • 將所有在 header 宣告的 boolformula 函式改為 static inline + 完整定義,包括:
      • 小 accessor:boolformula_lit_from_var, boolformula_var_from_lit, boolformula_lit_complement, boolformula_positive_lit
      • 建構/修改:boolformula_disjunction_unit/new, boolformula_conjunction_unit/new, boolformula_literal_new, boolformula_add, boolformula_set, boolformula_free, boolformula_neg
      • boolformula_copy(須放在 boolformula_to_cnf 之前,避免未宣告就使用)
      • add_clauses_to_boolformula(僅被 boolformula_to_cnf 使用,一併放進 header)
      • boolformula_to_cnf, boolformula_get_type, boolformula_get_length, boolformula_get_subformula, boolformula_get_value
    • C/C++ 相容:所有 malloc(sizeof(boolformula_t)) 改為 (boolformula_t*)malloc(sizeof(boolformula_t)),以便 C++ 編譯通過。
    • 僅保留宣告、不在 header 內定義:boolformula_print, boolformula_num_of_var
  • boolformula.c
    • 刪除所有已搬到 header 的函式定義,只保留:NOT_A_LITERALboolformula_printboolformula_num_of_var

效果:所有 include boolformula.h 的 .c/.cc 都能 inline 上述函式,且 C 與 C++ 皆可編譯。


4. cdnfformula(cdnfformula.h / cdnfformula.c)

  • cdnfformula.h
    • 加上:#include "type.h", "vector.h", "bitvector.h", "boolformula.h", <assert.h>, <stdlib.h>
    • 將所有 cdnfformula 的 inline 函式改為 static inline + 完整定義,包括:
      • cdnfformula_monomial_unit, cdnfformula_monomial_add, cdnfformula_monomial_M_DNF
      • cdnfformula_disjunction_unit/new/add/free, cdnfformula_conjunction_unit/new/add, cdnfformula_free
      • monomial_to_boolformula, dnf_to_boolformula, cdnfformula_to_boolformula
    • 僅保留宣告:cdnfformula_print, cdnfformula_eval_M_DNF
    • 型別修正cdnfformula_conjunction_new 回傳型別為 conjunction *(非 disjunction *)。
  • cdnfformula.c
    • 刪除所有已搬到 header 的函式定義,只保留:cdnfformula_monomial_to_string, cdnfformula_disjunction_to_string, cdnfformula_print, cdnfformula_eval_monomial, cdnfformula_eval_M_DNF

效果:所有 include cdnfformula.h 的 .c/.cc 都能 inline 上述函式。


5. c_examples / cpp_examples

  • c_examples/oracle.c
    • satisfible 若需被連結,改為 extern inline(或改為一般函式並在 header 宣告),讓該 .c 產出一個外部符號,連結時可解析。
  • C++ 編譯
    • 依賴 boolformula.h 內對 malloc 的顯式轉型,使 cpp_examples 能成功編譯。

四、為何這樣能「保留所有 inline」且能編譯

項目 說明
定義在 header 每個 include 該 header 的編譯單元都會看到完整函式本體,編譯器可以選擇 inline,不需依賴 LTO。
static inline 每個編譯單元有一份自己的定義,不產生外部符號,不會有重複定義或 undefined reference。
C/C++ 相容 malloc 結果做顯式轉型 (boolformula_t*)malloc(...),C 與 C++ 皆可編譯。
依賴順序 header 內依序 include type.h → vector.h → bitvector.h → boolformula.h(cdnfformula 再 include 上述),避免未定義型別或函式。
宣告順序 被呼叫的函式(如 boolformula_copyadd_clauses_to_boolformula)在呼叫者(如 boolformula_to_cnf)之前定義,避免隱式宣告。

五、建置結果

  • core:可成功編譯並產出 libcdnfp.a
  • c_examples:可成功編譯並連結出 learn(需 satisfible 有正確宣告/定義)。
  • cpp_examples:可成功編譯並連結(依賴 boolformula.h 的 malloc 轉型)。

整體而言:「在 header 內用 static inline 提供完整定義 + C/C++ 相容的 malloc 轉型」,既能保留所有 inline 的優化機會,又能讓專案在 C 與 C++ 下都成功編譯、連結。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant