青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

第一桶 從C到C++ 第七碗 陳老C演迭代開發 潘小P學漸進編程(之二)

     “在下一個版本里面我們不進行任何編碼工作。”老C道。
     “哦?那么我們要做些什么?”小P不解道。
     “我們來重新組織一下我們的工程。”老C解釋,“順便再討論一下文件結構的問題。”老C摸摸下巴,“你知道C語言的文件分為頭文件和源文件嗎?”
     “那是當然,就是.h和.c文件唄。”小P有些不以為然。
     “那你知道什么是translation unit 嗎?”老C接著問。
     “唔……那個東東是什么?”小P疑惑道。
     “那么你可以區分清楚什么是declaration,什么是definition嗎?”老C接著問。
     “一個是聲明,一個是定義……”
     “……我是問這兩個概念在C語言中的含義……”老C囧。
     “哦……”
     “看來我們需要進行一些基本的掃盲工作。”老C道,他讓小P從教研室的角落拉出白板,在上面寫下如下代碼。

int a;
extern int a;
extern int a = 5;

int Func (void);

int Func(void)
{
}


     “看看這些聲明有什么不同?”老C問道。
     “槑……”小P做沉思狀,“好像……這個……”
     “呵呵,這些代碼的不同之處在于是否分配存儲空間。”老C解釋道,“在我們對declaration和definition進行仔細講解前,我們先看看如 下概念。”老C又在白板上寫下如下文字,一邊寫一邊說:“你要記住,概念是最重要的,技巧是微不足道的,因為一旦你掌握了概念,看懂技巧是水到渠成的事 情,甚至自己也可以根據概念發明出一些小技巧出來……”

source file(preprocessing file)
preprocessing translation unit
translation unit

     “很遺憾,一般概念都伴隨一些晦澀的術語,而一般人則視術語如猛虎,認為術語只屬于學術,在一般的實際開發中沒有什么用處——然而我們組織邏輯的最基本單 位就是詞匯,如果我們在思考、交流的時候連基本的詞匯也無法理解,那么就根本談不上什么思考和交流了——畢竟大多數人類還是靠語言進行思考的,除了少數天 才使用圖形和符號進行思考;同時術語也簡化了我們交流的復雜度,比如我說PID,只要你理解了什么是PID這個概念,那么我就不用畫出框圖并解釋這個帶有 比例、積分和微分環節的反饋系統,這樣在行業內工作的人們可以方便的使用術語進行交流……羅嗦了這么多,只是希望你不要對這些晦澀的術語帶有排斥的心理, 而是要慢慢習慣它們,接受它們……雖然有些術語名字起得的確有些腦殘……”老C喋喋不休的說道。
     “呵呵……我明白了。”小P應道。
     “所謂source file,也可以說preprocessing file,就是程序中的源文件,一般就是我們寫的.c文件,這個文件的后綴一般由編譯器規定,但是行業內約定俗成的規定為.c,”老C指著source file開始解釋,“而preprocessing translation unit指的是某個源文件以及在它的前面使用#include預處理指令包含的頭文件和源文件。”說罷老C在白板上畫了幾個框框。
    
     “在這里,a.c就是preprocesing file,而a.c,a.h和b.c合起來稱為preprocessing translation unit。”老C指著他畫的框框,“哦,對了……這些框框表示文件……”
     “那么什么叫translation unit呢?”小P問。
     “就是經過preprocessing 后的preprocessing translation unit,你可以理解為a.c經過預處理后,在頭部將a.h和b.c內容展開后的某個中間件……”老C解釋道,“這樣不正規的解釋可以幫助你更快的理解……”
     “這些與declaration,definition有什么關系?”
     “當然有,在解釋什么是declaration和definition時,我們需要用到translation unit的概念。”老C答道,“因為translation unit中包含有external definition……”
     “等等,什么是external definition?”小P追問。
     “哦,為了解釋這些概念,我們先看看最初的那些例子,然后再熟悉一下這些術語。”老C指了指剛才在白板上隨意寫下的聲明示例,然后又在旁邊寫下了以下文字。

declaration
definition

     “所謂definition者,引起內存分配的declaration也……”老C開始轉文……
     “囧……請說地球話,反對火星語……”小P抗議。
     “呵呵,簡單的說,declaration說明了一組標識符的含義和屬性(A declaration specifies the interpretation and attributes of a set of identifiers),而definition就是引起內存分配的那些declaration——詳細來說,如果對于對象,導致了內存分配的動作;對 于函數,包含了函數體;對于枚舉常量或typedef名稱,就是declaration本身。 ”
     “哦……有些暈……”小P有些不明白。
     “好吧,簡單的說,definition是一些特殊的declaration,如果在聲明一個對象時,引起了存儲空間配分配于該對象,那么這個 declaration就是definition;如果在聲明一個函數時,這個聲明包含了函數體,那么這個declaration就是 definition;如果是枚舉常量和typedef,那么這些declaration本身就是definition。這下可明白?”老C耐心的解釋起 來。
     “嗯,就是說definition其實就是一些特殊的declaration,是吧?”小P有些理解,“但是在C里面怎么會有對象啊?”
     “哦,基本上可以這樣理解。”老C回答小P的前一個問題,然后又開始回答下一個,“所謂對象,不過是統稱,比如int a,a就是int的一個對象,如果你不習慣使用對象這個術語,我們可以用object來代替。”然后他指著上面的代碼例子,“你來寫寫哪些是 declaration,哪些是definition吧。”
     “如果圖省事,這些全部都是declaration……”小P自作聰明。
     “囧……對是對,可是……我說你就不能嚴肅一些嗎?”
     “呵呵,開玩笑的,何必當真呢?”小P一邊說,一邊在旁邊寫下注釋。

int a;              // definition
extern int a;       // declaration
extern int a = 5;   // ?

int Func (void);    // declaration

int Func(void)      // definition
{
}

     “有一個不知道是什么,所以我畫了問號。”小P指著代碼說道。
     “沒有關系,我們先不管它到底是什么,我們再來看看其它幾個概念。”老C沒有著急給出小P答案,而是在白板上的一塊空白地方又寫下如下文字。

external linkage
internal linkage
none linkage

     “一個標識符(identifier),如果在不同的scope中被聲明,或者在同一個scope中被多次聲明,它總會被正確的指向同一個object或 者function,這一過程叫做linkage。”老C解釋,“比如我有兩個文件,a.c和b.c,一個函數FuncA()在a.c中定義,如果你想在 b.c中的FuncB()函數中使用函數FuncA(),在b.c中你可以這樣寫……”老C又開始在白板上涂抹。

a.c:
void FuncA(void)
{
}


b.c:
extern void FuncA (void);

void FuncB(void)
{
    FuncA();
}

     “喏,你只要在b.c中聲明這個函數就可以了,你看,函數被聲明了兩次——注意定義是聲明的特例——如果你的兩個文件被正確的編鏈,那么C語言規范保證可 以找到正確的FuncA()。”老C在白板上指指點點,“同時要注意,這里說的是聲明多次,可沒有說定義多次,如果你把函數定義了超過一次,那么編鏈的時 候會報錯的……”老C咽了一口唾沫,“這個就是external linkage的一個例子。而且根據C ISO/IEC 9899規范,我們甚至不用在b.c中FuncA()函數的聲明前加exern,編鏈器一樣可以正確的找到FuncA()的定義。”
     “哦?是嗎?那么我到要試試……”小P有些好奇。
     “嗯,你等等再試。我再來說說internal linkage。”老C開始更改他在白板上寫下的代碼,“如果我在FuncA()的聲明前加上static,那么其它的translation unit無論如何無法找到這個函數。”

a.c:
static void FuncA(void)
{
}

     “如果這個時候我們的代碼還是b.c的樣子,就會產生一個編鏈錯誤,告訴我們無法解析FuncA這個標識符。”老C道,“這個就是一個internal linkage的例子。”
     “那么none linkage呢?”小P追問。
     “……自己看看 ISO/IEC 9899規范吧……”老C覺得小P自己也得花些功夫了,“下面我們就來詳細看看external definitions。這里之所以講external,是因為這些definitons都在函數外部……什么?你不知道可以在函數內部定義和聲明函 數?……這樣也好,這是C語言的怪癖……我們不管那么多,先看看又有哪些概念需要了解的……”老C撓撓頭,“哦,可能之前我們得先了解一下什么是 scope。”
     “scope?就是作用域吧?”小P問。
     “嘶……”老C抽了一口氣,“我不知道怎么解釋,在我理解作用域還包括了name spaces的概念,因此我更喜歡使用scope這個術語而不是很具有內涵的作用域這個術語。”
     “C語言也有name spaces嗎?”小P不解。
     “有啊……自己去看吧。”老C不想多費口舌,“所謂scope,又分為以下幾種……”他又在白板上涂抹起來。

function scope
file scope
block scope
function prototype scope

     “呵呵,”老C笑道,“file scope最好解釋,如果一個標識符沒有被聲明到其它三個scope當中,那么它的scope就是file scope……至于其它三個scope的含義,我建議你……”
     “……去看規范……”小P囧。
     “哈哈……”老C突然覺得這是一個少費口舌的好辦法,“其實簡單的理解,file scope就是我們一般聲明的全局變量和函數,因為規范是很嚴肅的東西,所以才寫得那么羅嗦和晦澀,因為總有人喜歡找一些特殊的情況以顯示自己對規則的藐 視,所以規范不得不那么面面俱到……好啦好啦,我也是胡說的,呵呵。你只要知道我們說的external definitions是在file scope中的定義就好了。在進入我們正式的議題前,我再磨蹭一下。”說完老C在白板上寫下如下文字。

storage-class specifiers:
typedef
extern
static
auto
register

     “我們主要討論extern和static,但是其它的你也要了解一下,所以……”
     “……看規范……”
     “呵呵,好了好了,我們現在來說說external definitions吧。”老C覺得小P真是善解人意啊,“這里你只要了解一些簡單的規則就可以了。第一,function的規則與object不同; 第二,如果你沒有將function或者object聲明為static,那么它們自動的成為extern;第三,object的規則比較復雜一些,這 樣,我來說你來寫……”老C揉揉手,想偷懶一下,“這樣你印象比較深刻……”
     “囧……好吧……”小P不情愿的回應,拿起彩筆一邊聽老C講,一邊在白板上寫下如下內容。

1. 聲明一個object,若它的scope是file scope,且它被初始化,那么它的聲明就是一個external definition.
2. 聲明一個object,若它的scope是file scope,且它沒有被初始化,且它沒有storage-class specifier,或者它的storage-class specifier是static,則此聲明就被命名為tentative definition。如果一個translation unit中有一個或多個關于此一標識符的tentative definition,并且在此translation unit中沒有關于此標識符的external definition,那么此標識符會被當作此translation unit中的一個file scope的一個declaration,其作用在整個file scope中,且有一個0初始化值。
3. 如果一個標識符的聲明是tentative definition,并且有external linkage,則此被聲明的類型不能是不完整的類型。
4. 如果一個變量其聲明前帶有extern storage-class specifier,則其是否是exernal或internal linkage要視其前面是否有在scope中可見的此相同變量的聲明,如果有,則其跟隨前一相同變量的聲明,否則就是exernal linkage。
4. 同一個標識在一個translation unit當中即表現exernal linkage,又表現internal linkage,則其行為未定義。

     “唔……不是很好理解。”小P抱怨。
     “呵呵,我們來看幾個例子好了。這些標識符都被聲明在一個translation unit當中。”老C說道,“但是我想提醒一下,external definition與external linkage的external含義完全不同,不要搞混淆了。”然后他在小P寫的話下面又增加了一組代碼。

int i1 = 1;              // definition, external linkage
static int i2 = 2;       // definition, internal linkage
extern int i3 = 3;       // definition, external linkage
int i4;                  // tentative definition, external linkage
static int i5;           // tentative definition, internal linkage

int i1;                  // valid tentative definition, refers to previous
int i2;                  // undefined, linkage disagreement
int i3;                  // valid tentative definition, refers to pre vious
int i4;                  // valid tentative definition, refers to pre vious
int i5;                  // undefined, linkage disagreement

extern int i1;           // refers to previous, whose linkage is external
extern int i2;           // refers to previous, whose linkage is internal
extern int i3;           // refers to previous, whose linkage is external
extern int i4;           // refers to previous, whose linkage is external
extern int i5;           // refers to previous, whose linkage is internal

int i[];                 // the array i still has incomplete type, the implicit initializer causes it to have one element, which is set to
                         // zero on program startup.


     “我想提醒一下,這里只是做說明,在實際編碼時我們可不要這么寫。”老C強調,“那么現在你是否明白extern int a = 5 是declaration還是definition了嗎?”
     小P仔細看了看老C寫的示例代碼,又把自己寫的話念了幾遍,說道:“嗯,這樣看來這個語句應當是具有exernal linkage 的exernal definition。”
     “呵呵,不錯,我再總結一下。你可以簡單的理解為如果一個變量在聲明時被初始化,那么這個聲明就成為一個定義,而與storage-class specifier無關,如果其前面有storage-class specifier,那么只能說明其是否是internal linkage或external linkage;如果一個變量在聲明時前面帶有extern,且沒有被初始化,那么它就是一個declaration,且其是否是external linkage要視前面是否有其它此相同變量的聲明,如果有,則其跟隨前面這一相同變量的聲明,如果沒有,則其為external linkage;聲明總是傾向于exernal linkage,如果你不聲明static;根據規則不能出現既是internal linkage又是external linkage的情況,否則其行為無定義。”老C覺得十分渴,找到茶杯大大的喝了一口水。    

     “好吧,我承認很復雜……可是這個和我們討論的內容有什么關系呢?”小P有些云里霧里。
     “呵呵,只是一些理論基礎。”老C答道,“根據規則我們可以使用各種各樣的組合來管理我們的代碼,設計我們的文件組織,但是在實際開發中自然有一定的規 則。如果你按照這種規則進行編碼,那么基本上不用關注這些標準的細節,當然,出現錯誤的時候你還是要根據標準來查找可能出錯的地方。”
     “哦?是嗎?說來聽聽?”小P問。
     “好吧。”老C答道。“我們以前討論過,我們人類對于復雜事物的處理能力是有限的,為了解決這些復雜問題,我們總是希望把它們分解成我們可以理解的規模。 通過信息隱藏的方式,我們可以將一個很大規模的問題分解分解再分解,直到我們的智力可以管理這些問題。而使用文件對代碼進行劃分,可以有效的幫助我們對問 題的規模進行控制——眼不見,心不亂嘛。”
     “哦,具體怎么做呢?能不能舉個簡單的例子?”小P問道。
     “可以啊。”老C答道,然后指揮小P將白板擦干凈,又在上面開始比劃,“一個比較簡單的問題,求解一個方程。”他在白板上寫下如下文字。

ax2 + bx + c = 0

     “我們可以這樣來分解問題。”老解釋,“設計一個函數,其返回值為實根的個數,0為沒有實根,1為有兩個相等的實根,2為有兩個不等實根,3為有無窮多解,-1為無解。實根作為出口參數,設計為函數接口的一部分。我們把這個函數放到solve.c文件中。”

solve.c:
int Solve (float a, float b, float c, float* root1, float* root2);

int Solve(float a, float b, float c, float* root1, float* root2)
{
}

     “這樣如果我們在某個項目中需要解一個二元一次方程,那么我們,比如在main.c中,就可以很簡單的這樣寫。”老C接著在白板其它地方寫道。

main.c:
extern int Solve (float a, float b, float c, float* root1, float* root2);

int main()
{
    float root1, root2;

    ...
    Solv(1, -1, 1, &root1, &root2);
    ...
}

     “只要我們將solve.c正確的添加到我們的工程中就可以了。”老C道。
     “這樣寫有什么好處呢?”小P問。
     “好處嘛,最明顯的是……復用,而且就算是我們要自己寫Solve()函數,現在它也與main()函數分開,人為的將兩個關系比較遠的模塊分開,這樣可 以強制的控制代碼的規模。”老C點點頭,“如果我們將extern 語句放入一個名叫solve.h的文件中,那么就更方便了。”

solve.h:
#if !defined(SOLVE_H_)
#define
SOLVE_H_

extern int Solve (float a, float b, float c, float* root1, float* root2);

#endif /*
SOLVE_H_ */

main.c:
#include "solve.h"

int main()
{
   
float root1, root2;

    ...
    Solve(1, -1, 1, &root1, &root2);
    ...
}

     “這樣的好處呢?”小P問。
     “簡單,減少冗余。如果我們solve.c中有很多可以讓其它文件使用的函數,這樣就不用在其它文件頭部寫出很多的extern...的聲明,而只用在solve.h中寫一次,在其它文件中#include就可以了。”老C補充道,“偷懶,是程序員的美德……”
     “這里為什么要用.h文件呢?我用一個.c文件,在里面寫入extern...的聲明不行嗎?”小P接著問。
     “……沒有什么不行,但,不符合行規……而且如果你使用automake工具的話,可能配置起來要麻煩一些……總之不要在這些地方釋放你多余的創造力,別 人怎么做的你就怎么做,這個是行業內的規矩……”老C有些郁悶,心想這真是一個多動的家伙啊,“而且最好在.h文件中只出現聲明而不要出現定義,這樣你在 編譯的時候鏈接錯誤會少很多很多。”
     “為什么在solve.c文件的前面要先寫一個int Solve (float a, float b, float c, float* root1, float* root2)?”小P指著白板問。
     “函數原型,這個就叫做function prototype。”老C解釋,“當然你也可以不用寫,但是根據行業內許多經驗的總結,這樣寫總有好處,因為據說這樣在編譯的時候可以讓編譯器在函數調 用點做全面的類型檢查。”老C指著solve.c下面的代碼說,“其實這里又出現一處冗余,因為在solve.c和solve.h文件中,Solve() 函數被聲明了兩次,這樣在Solve()函數接口被修改的時候,我們不得不修改兩處地方,而這是我們很討厭的事情。”
     “那么有什么解決方法呢?”小P問。
     “我們可以在solve.c中包含solve.h,這樣就可以了。”老C說,“然后我們可以進行解決問題的細節工作。”他又在白板上比劃起來。

solve.c:
#include "solve.h"
#include <math.h>

#define EPSILON    0.000001F

static float Solve1stOrder (float b, float c);
static float Delta (float a, float b, float c);
static float DoSolve (float a, float b, float sqrtDelta);

int Solve(
float a, float b, float c, float* root1, float* root2)
{
    int   rootNum;
    float delta;
    float sqrtDelta;

  
    /* If a is 0, then the formula becomes 1st order. */
    if ((a < EPSILON) && (a > -EPSILON))
    {
        if ((b < EPSILON) && (b > -EPSILON))
        {/* b is 0 */
            if ((c < EPSILON) && (c > -EPSILON))
            {/* If c is 0, the formula has
infinite roots. */
                rootNum = 3;
               
                return rootNum;
            }
            else
            {/* If c is not 0, the formula has no root. */
                rootNum = -1;
               
                return rootNum;
            }
        }
        else       
        {/* b is not 0 */
            rootNum = 1;           
           
*root1 = *root2 = Solve1stOrder(b, c);

           
return rootNum;     
        }      
    }

    delta = Delta(a, b, c);

    /* If delta < 0, the formula has no real root. */
    if (delta < 0)
    {
        rootNum = 0;
       
        return rootNum;
    }

    /* If delta is 0, the formula has two equal real roots. */
    if ((delta < EPSILON) && (delta > -EPSILON))
    {
        rootNum = 1;
        *root1 = *root2 = (-b) / (2 * a);
   
        return rootNum;
    }

    /* If delta > 0, the formula has two different real roots. */
    if (delta > 0)
    {
        rootNum = 2;
        sqrtDelta = sqrt(delta);
        *root1 = DoSolve(a, b, sqrtDelta);
        *root2 = DoSolve(a, b, -sqrtDelta);

        return rootNum;
    }
}


static
float Solve1stOrder(float b, float c)
{
    return (-c) / b;
}

static float Delta(float a, float b, float c)
{
    return b * b - 4 * a * c;
}

static float DoSolve(float a, float b, float sqrtDelta)
{
    return (-b + sqrtDelta) / (2 * a);
}

     “看,一些具體的解題過程我們并不想暴露給其它文件,所以使用static將其聲明為internal linkage,這樣就相當于隱藏了信息;而Solve()函數是我們希望暴露給其它文件的,所以使用extern將其聲明為external linkage——這樣以文件為單位,我們組織了一個程序的模塊,并向其它模塊提供了接口,以供其它模塊使用。”看到小P還在看代碼,老C接著解釋道,“ 哦,EPSILON這里只是一個需要注意的小技巧,因為你不能比較兩個float數值是否相等,只能比較它們的差是否小于一個很小的數值,來判斷它們是否 相等……原因?……與浮點數在內存中的存放格式有關系。總之你認為浮點數的最后幾位總是隨機的就可以了。”
     “哦,這樣我就明白了。”小P點點頭,“那么這個solve.h中的條件編譯是怎么回事?”
     “哦,這也是一些小技巧,用于防止頭文件被重復的包含而可能導致的遞歸。你只要認為#include是將其所引用的文件原封不動的放到引用點就可以理解 了,”老C撓撓頭,“比如a.c包含a.h和b.h,而a.h包含c.h,b.h也包含c.h,那么c.h的這些條件編譯可以防止c.h在a.c中被包含 兩次。你可以自己在#include的包含處將文件展開看看就明白了。”
     “是么?”小P在紙上畫了幾下,“哦,這樣我就清楚了。呵呵。但是……有沒有包含.c文件的情況呢?”小P又開始發揮想象力。
     “唔……有的……”老C撓撓頭,“在某些需要裁剪和定制的項目中也許會根據某個.h文件中的條件編譯來選擇是否包含某些.c文件,但……這些工作也可以由 makefile來完成,而且感覺大多數的做法都是采用腳本+makefile完成的……無論怎么樣,你現在先不要使用包含.c文件的做法,等熟悉了以后 我們再慢慢研究……”他搓搓手,“好吧,廢話說了這么多的一大堆,我們也去休息休息睡午覺吧,下午3點到教研室,我們接著聊。”老C有些乏力的說。
     “呵呵,好啊好啊。”兩人一邊說一邊向門口走去……

(繼續等待v0.03……)

posted on 2009-02-04 16:42 Anderson 閱讀(1979) 評論(3)  編輯 收藏 引用

評論

# re: 第一桶 從C到C++ 第七碗 陳老C演迭代開發 潘小P學漸進編程(之二)[未登錄] 2009-02-04 20:58 ypp

嘿嘿,看完,非常有幫組,繼續等待樓主的佳作。  回復  更多評論   

# re: 第一桶 從C到C++ 第七碗 陳老C演迭代開發 潘小P學漸進編程(之二) 2009-02-04 22:28 岳陽

小P真幸福啊。遇到了名師。  回復  更多評論   

# re: 第一桶 從C到C++ 第七碗 陳老C演迭代開發 潘小P學漸進編程(之二) 2009-02-05 02:03 imnobody

其實,俄已經等好幾天了^^  回復  更多評論   


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


<2009年2月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
1234567

導航

統計

常用鏈接

留言簿(6)

隨筆檔案(21)

文章檔案(1)

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产精品热久久| 亚洲图片欧美日产| 欧美精品二区| 欧美日韩 国产精品| 亚洲视频观看| 一区二区免费在线视频| 久久久久免费视频| 亚洲精品在线看| 欧美刺激午夜性久久久久久久| 欧美在线视频免费播放| 亚洲国内精品在线| 亚洲精品久久久久久久久久久久 | 午夜精品久久久| 久久精选视频| 亚洲图片在线| 久久露脸国产精品| 欧美一区二区三区四区在线观看地址 | 欧美一进一出视频| 免费亚洲电影在线| 国产精品超碰97尤物18| 狠狠色综合网站久久久久久久| 亚洲精品国产精品乱码不99按摩| 亚洲一区二区三区在线视频| 亚洲第一黄色| 亚洲天天影视| 亚洲手机在线| 一本色道精品久久一区二区三区 | 开心色5月久久精品| 亚洲国产欧美一区二区三区同亚洲 | 午夜精品一区二区三区电影天堂| 久久久美女艺术照精彩视频福利播放| 欧美精品色一区二区三区| 久久精品综合网| 午夜精品www| 欧美日本韩国一区二区三区| 精品av久久707| 欧美在线观看一区二区三区| 亚洲欧美另类在线观看| 亚洲三级性片| 久久九九国产精品| 亚洲天堂av综合网| 欧美日韩天堂| 国产精品久久| 亚洲区一区二区三区| 亚洲视频一二三| 欧美日韩成人在线视频| 亚洲二区在线| 亚洲国产综合在线| 亚洲国产另类久久久精品极度| 国内外成人免费激情在线视频 | 好吊妞**欧美| 久久天天躁狠狠躁夜夜av| 米奇777在线欧美播放| 久久婷婷影院| 午夜精品久久99蜜桃的功能介绍| 欧美视频免费| 亚洲制服少妇| 久久精品国产亚洲一区二区三区 | 亚洲自拍偷拍福利| 久久综合伊人77777| 国产精品欧美风情| 美女脱光内衣内裤视频久久影院| 久久国产免费| 国产婷婷色一区二区三区| 欧美与欧洲交xxxx免费观看| 麻豆国产精品va在线观看不卡| 亚洲一区视频在线观看视频| 国产精品你懂的在线| 激情国产一区二区| 亚洲精品免费在线| 亚洲国产高清在线观看视频| 免费日本视频一区| 国产精品三上| 久久久精品一区二区三区| 欧美在线视频免费播放| 亚洲第一色在线| 午夜在线播放视频欧美| 午夜精品久久久久久99热软件| 久久久亚洲高清| 亚洲国产毛片完整版| 亚洲精品欧美激情| 亚洲精美视频| 欧美精品久久一区| 午夜精品久久久久久久99黑人| 小嫩嫩精品导航| 在线观看一区二区精品视频| 亚洲自拍啪啪| 欧美成人tv| 亚洲一区美女视频在线观看免费| 久久久一区二区三区| 亚洲精品欧美在线| 亚洲一区自拍| 亚洲国产99| 久久午夜av| 亚洲性人人天天夜夜摸| 黄色成人在线免费| 一区二区三区欧美在线观看| 久久夜色精品国产亚洲aⅴ| 欧美一区二区三区久久精品| 激情综合中文娱乐网| 亚洲美女网站| 欧美顶级艳妇交换群宴| 国产伦精品一区二区三区在线观看 | 欧美精品一区二区三区蜜桃| 午夜在线精品| 欧美久久视频| 美女999久久久精品视频| 欧美三日本三级少妇三2023| 另类av导航| 国产午夜精品视频免费不卡69堂| 洋洋av久久久久久久一区| 玖玖综合伊人| 在线播放日韩专区| 亚洲欧美一区二区精品久久久| 你懂的国产精品| 午夜精品福利视频| 亚洲一区bb| 国产精品二区三区四区| 中日韩美女免费视频网址在线观看| 亚洲午夜精品久久久久久app| 欧美另类极品videosbest最新版本| 小嫩嫩精品导航| 欧美亚洲免费电影| 亚洲欧美国产制服动漫| 亚洲欧美成人| 亚洲欧美日韩中文视频| 欧美日本国产精品| 午夜一区二区三区在线观看| 欧美精品久久久久久| 亚洲一区二区在线免费观看| 欧美a一区二区| 欧美激情综合色| 亚洲国产视频a| 99在线精品免费视频九九视| 欧美另类69精品久久久久9999| 鲁鲁狠狠狠7777一区二区| 毛片基地黄久久久久久天堂| 久久久999精品| 麻豆精品精品国产自在97香蕉| 久久精品视频一| 男女激情久久| 中文日韩电影网站| 欧美色精品在线视频| 欧美在线黄色| 国产一区二区三区四区hd| 久久国产精品99国产| 99精品欧美一区| 欧美大色视频| 亚洲国产视频一区二区| 欧美阿v一级看视频| 亚洲男同1069视频| 久久精品免费| 免费日韩视频| 亚洲精品久久久久久久久久久久 | 亚洲在线一区二区三区| 久久精品国产清自在天天线| 亚洲国产日韩欧美| 欧美成人久久| 卡一卡二国产精品| 国产精品v欧美精品∨日韩| 久久精品欧洲| 在线观看欧美亚洲| 欧美日韩 国产精品| 午夜免费电影一区在线观看| 另类图片综合电影| 亚洲午夜高清视频| 伊人久久大香线蕉av超碰演员| 一区二区三区欧美日韩| 亚洲国产专区校园欧美| 欧美日韩午夜在线| 久久国产精品72免费观看| 亚洲精品免费一区二区三区| 欧美一级网站| 亚洲美女视频网| 玖玖视频精品| 久久精品99久久香蕉国产色戒| 久久综合给合久久狠狠狠97色69| 亚洲视频图片小说| 国产亚洲一区二区三区在线观看| 久久综合色婷婷| 久久成人免费日本黄色| 亚洲国产精品一区在线观看不卡 | 国产精品视频观看| 久热精品在线视频| 久久阴道视频| 国产在线不卡| 欧美视频日韩| 老司机aⅴ在线精品导航| 一区二区三区精品国产| 欧美黑人国产人伦爽爽爽| 欧美一区=区| 亚洲天堂成人在线观看| 亚洲电影一级黄| 免费日韩精品中文字幕视频在线| 亚洲一区二区三区高清不卡| 亚洲你懂的在线视频| 亚洲精品女av网站| 欧美伦理a级免费电影| 欧美在线视频免费观看| 久久尤物视频|