靈修分享:亞略巴古的演講

亞略巴古的演說是使徒行傳一篇非常著名的講道。基督徒往往用這段經文來說明上帝的屬性,同時也會參考這段經文作為和外邦人互動的一個參考方式。最近因為團契查經查到這一段,重新思想後看到了以前沒有考慮過的面向,在這邊記錄一下。

徒17:16-34保羅在雅典等候他們的時候,看見滿城都是偶像,就心裏着急;於是在會堂裏與猶太人和虔敬的人,並每日在市上所遇見的人,辯論。還有伊壁鳩魯和斯多亞兩門的學士,與他爭論。有的說:「這胡言亂語的要說甚麼?」有的說:「他似乎是傳說外邦鬼神的。」這話是因保羅傳講耶穌與復活的道。他們就把他帶到亞略‧巴古,說:「你所講的這新道,我們也可以知道嗎?因為你有些奇怪的事傳到我們耳中,我們願意知道這些事是甚麼意思。」(雅典人和住在那裏的客人都不顧別的事,只將新聞說說聽聽。)
保羅站在亞略‧巴古當中,說:「眾位雅典人哪,我看你們凡事很敬畏鬼神。我遊行的時候,觀看你們所敬拜的,遇見一座壇,上面寫着『未識之神』。你們所不認識而敬拜的,我現在告訴你們。創造宇宙和其中萬物的神,既是天地的主,就不住人手所造的殿,也不用人手服事,好像缺少甚麼;自己倒將生命、氣息、萬物,賜給萬人。他從一本本:有古卷是血脈造出萬族的人,住在全地上,並且預先定準他們的年限和所住的疆界,要叫他們尋求神,或者可以揣摩而得,其實他離我們各人不遠;我們生活、動作、存留,都在乎他。就如你們作詩的,有人說:『我們也是他所生的。』我們既是神所生的,就不當以為神的神性像人用手藝、心思所雕刻的金、銀、石。世人蒙昧無知的時候,神並不監察,如今卻吩咐各處的人都要悔改。因為他已經定了日子,要藉着他所設立的人按公義審判天下,並且叫他從死裏復活,給萬人作可信的憑據。」
眾人聽見從死裏復活的話,就有譏誚他的;又有人說:「我們再聽你講這個吧!」於是保羅從他們當中出去了。 但有幾個人貼近他,信了主,其中有亞略‧巴古的官丟尼修,並一個婦人,名叫大馬哩,還有別人一同信從。

對基督徒來說,保羅這篇講道講的真好,不但講出了上帝的超越性(像是不住人手所造的殿、也不是金銀石的彫刻),也帶出了耶穌基督復活的大能。但最近我才注意到眾人的反應:「眾人聽見從死裏復活的話,就有譏誚他的;又有人說:「我們再聽你講這個吧!」」不曉得你看到這一段有什麼感想?可能我是玻璃心吧,如果我是保羅,我大概會非常非常的難過,看起來似乎沒有人理會這個福音、這篇講道。這篇被基督…

Variant Arguments

在C/C++(C89)中,有所謂的variant argument(變動引數)這東西。說穿了,就是讓使用者可以輸入不定長度的參數,最著名的例子就是 printf 這個大家都會用的函式。下面就來看看實際上的用法。

首先,在宣告函數上,在所要帶入的參數部分用「...」來表示,如下所示:


void func(int, ... );

這樣就可以讓編譯器不檢查所輸入的參數型態跟數量(但為什麼在 ... 前面還要在多一個參數呢?容後在述)。但是,比較大的麻煩是,我們要如何將所要的參數取出來呢?在 stdarg.h (在 C++ 則是 cstdarg) 有提供一個好用的型態以及一些巨集,分別列在下面:

type:
va_list: type for iterating arguments

macros:
va_start: Start iterating arguments with a va_list
va_arg: Retrieve an argument
va_end: Free a va_list
va_copy: Copy contents of one va_list to another(這是 C99 的標準)

我們先來看看一個實際的例子。下面的函式,第一個參數代表的是總共有 n 個參數(不含他自己),然後把後面所有的參數都印出來(並且假設後面所有的參數型態都是 int )



void func(int n, ...)
{
va_list args;

va_start(args, n);

while(n>0)
{
printf("%d\n", va_arg(args, int));
n--;
}
va_end(args);
}


讓我們看看實際的定義:
In stdarg.h...
typedef __builtin_va_list __gnuc_va_list;
typedef __gnuc_va_list va_list;
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
#define va_copy(d,s) __builtin_va_copy(d,s)

接下來比較麻煩的地方在於,那一連串的 __builtin_ 函式要到哪去找呢?看到 __builtin_ 開頭的 symbol,這些都是 GCC 內部的實做,也就是說,放棄吧~既然新版的看不到東西,我們來看看舊版的實作方式,但要特別一提的是,GCC 再也不支援下面的實作方式~


In vadefs.h...

typedef char * va_list;
#define _ADDRESSOF(v) ( &reinterpret_cast < const char & > (v) )
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap) ( ap = (va_list)0 )

In stdarg.h...

#define va_start _crt_va_start
#define va_arg _crt_va_arg
#define va_end _crt_va_end

首先,從這裡可以看出va_list其實只是一個char*,它將整串引數當成一個位元陣列。而 va_start 不過就是將第一個參數的位置再加上第一個參數的大小,如此而已。而每次在取值也都是使用相同的手法。這也告訴我們為什麼在宣告函數的時候一定要有第一個參數。至於為什麼要使用_INTSIZEOF而不直接使用 sizeof,最主要的因素在於 X86 的系統上,會有對齊 sizeof( int )的現象發生,所以我們勢必也要做好對齊的動作(不過這動作寫的真漂亮,學起來)換句話說,如果換到其他的系統,則這一步驟不一定是必須的,可能簡單的使用 sizeof 就好了。

留言

這個網誌中的熱門文章

如何將Linux打造成OpenFlow Switch:Openvswitch

我弟家的新居感恩禮拜分享:善頌善禱

如何利用 Wireshark 來監聽 IEEE 802.11 的管理封包