摘要:所謂的隐函數就是隻在本.c,或者.cpp檔案中聲明( 沒在頭檔案中聲明的函數)的函數. 對于其非本檔案的稱之為隐世函數.
萬惡之源:C語言中的隐式函數聲明
今天在調用postgresql源碼中get_rel_name()函數時,不小心調用了隐函數get_relation_name();出現
delrelation_record.c:70:16: warning: implicit declaration of function ‘get_relation_name’ [-Wimplicit-function-declaration]
table_name = get_relation_name(relOid);
^~~~~~~~~~~~~~~~~
delrelation_record.c:70:14: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
table_name = get_relation_name(relOid);
^
delrelation_record.c:92:5: warning: ‘res’ may be used uninitialized in this function [-Wmaybe-uninitialized]
PQclear(res);
這裡 我們比較比較get_rel_name() 和 get_relation_name() 有什麼不同.
首先:看源碼get_rel_name();
src/backend/utils/cache/lsyscache.c
char *
get_rel_name(Oid relid)
{
HeapTuple tp;
tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
if (HeapTupleIsValid(tp))
{
Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
char *result;
result = pstrdup(NameStr(reltup->relname));
ReleaseSysCache(tp);
return result;
}
else
return NULL;
}
然後看get_relation_name();
src/backend/utils/adt/ruleutils.c
/*
* get_relation_name
* Get the unqualified name of a relation specified by OID
* 和get_rel_name() 函數的不同就是多了一個判斷error的條件.
* This differs from the underlying get_rel_name() function in that it will
* throw error instead of silently returning NULL if the OID is bad.
*/
static char *
get_relation_name(Oid relid)
{
char *relname = get_rel_name(relid);
if (!relname)
elog(ERROR, "cache lookup failed for relation %u", relid);
return relname;
}
按理說調用哪個都可以啊.然後再看看函數聲明的位置.
get_relation_name() 在src/backend/utils/adt/ruleutils.c 和函數聲明在有一個文檔裡.
static char *get_relation_name(Oid relid);
而get_rel_name() 在src/include/commands/extension.h 在頭檔案裡,
外界函數想要調用它,隻需添加頭問價就可以.
extern Oid get_extension_oid(const char *extname, bool missing_ok);
是以,舉個例子就會很容明白隐函數的用途.防止被外界調用.