• <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>
            posts - 19,  comments - 21,  trackbacks - 0
            一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:
                1). 并行設備的硬件寄存器(如:狀態寄存器)
                2). 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)
                3). 多線程應用中被幾個任務共享的變量
                回答不出這個問題的人是不會被雇傭的。我認為這是區分C程序員和嵌入式系統程序員的最基本的問題。嵌入式系統程序員經常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。不懂得volatile內容將會帶來災難。
                假設被面試者正確地回答了這是問題(嗯,懷疑這否會是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。
                1). 一個參數既可以是const還可以是volatile嗎?解釋為什么。
                2). 一個指針可以是volatile 嗎?解釋為什么。
                3). 下面的函數有什么錯誤:
                     int square(volatile int *ptr)
                     {
                          return *ptr * *ptr;
                     }
                下面是答案:
                1). 是的。一個例子是只讀的狀態寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它。
                2). 是的。盡管這并不很常見。一個例子是當一個中服務子程序修該一個指向一個buffer的指針時。
                3). 這段代碼的有個惡作劇。這段代碼的目的是用來返指針*ptr指向值的平方,但是,由于*ptr指向一個volatile型參數,編譯器將產生類似下面的代碼:
                int square(volatile int *ptr)  
                {
                     int a,b;
                     a = *ptr;
                     b = *ptr;
                     return a * b;
                 }
                由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
                 long square(volatile int *ptr)  
                 {
                        int a;
                        a = *ptr;
                        return a * a;
                 }

            講講我的理解: (歡迎打板子...~~!)

            關鍵在于兩個地方:      
              
            1. 編譯器的優化  (請高手幫我看看下面的理解)

            在本次線程內, 當讀取一個變量時,為提高存取速度,編譯器優化時有時會先把變量讀取到一個寄存器中;以后,再取變量值時,就直接從寄存器中取值;

            當變量值在本線程里改變時,會同時把變量的新值copy到該寄存器中,以便保持一致

            當變量在因別的線程等而改變了值,該寄存器的值不會相應改變,從而造成應用程序讀取的值和實際的變量值不一致

            當該寄存器在因別的線程等而改變了值,原變量的值不會改變,從而造成應用程序讀取的值和實際的變量值不一致  


            舉一個不太準確的例子:  

            發薪資時,會計每次都把員工叫來登記他們的銀行卡號;一次會計為了省事,沒有即時登記,用了以前登記的銀行卡號;剛好一個員工的銀行卡丟了,已掛失該銀行卡號;從而造成該員工領不到工資  

            員工 -- 原始變量地址  
            銀行卡號 -- 原始變量在寄存器的備份  


            2. 在什么情況下會出現(如1樓所說)

                1). 并行設備的硬件寄存器(如:狀態寄存器)  
                2). 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)  
                3). 多線程應用中被幾個任務共享的變量  
                

            補充: volatile應該解釋為“直接存取原始內存地址”比較合適,“易變的”這種解釋簡直有點誤導人;  

            “易變”是因為外在因素引起的,象多線程,中斷等,并不是因為用volatile修飾了的變量就是“易變”了,假如沒有外因,即使用volatile定義,它也不會變化;

            而用volatile定義之后,其實這個變量就不會因外因而變化了,可以放心使用了; 大家看看前面那種解釋(易變的)是不是在誤導人


            ------------簡明示例如下:-----------------

            volatile關鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素更改,比如:操作系統、硬件或者其它線程等。遇到這個關鍵字聲明的變量,編譯器對訪問該變量的代碼就不再進行優化,從而可以提供對特殊地址的穩定訪問。
            使用該關鍵字的例子如下:
            int volatile nVint;
            >>>>當要求使用volatile 聲明的變量的值的時候,系統總是重新從它所在的內存讀取數據,即使它前面的指令剛剛從該處讀取過數據。而且讀取的數據立刻被保存。
            例如:
            volatile int i=10;
            int a = i;
            ...
            //其他代碼,并未明確告訴編譯器,對i進行過操作
            int b = i;
            >>>>volatile 指出 i是隨時可能發生變化的,每次使用它的時候必須從i的地址中讀取,因而編譯器生成的匯編代碼會重新從i的地址讀取數據放在b中。而優化做法是,由于編譯器發現兩次從i讀數據的代碼之間的代碼沒有對i進行過操作,它會自動把上次讀的數據放在b中。而不是重新從i里面讀。這樣以來,如果i是一個寄存器變量或者表示一個端口數據就容易出錯,所以說volatile可以保證對特殊地址的穩定訪問。
            >>>>注意,在vc6中,一般調試模式沒有進行代碼優化,所以這個關鍵字的作用看不出來。下面通過插入匯編代碼,測試有無volatile關鍵字,對程序最終代碼的影響:
            >>>>首先,用classwizard建一個win32 console工程,插入一個voltest.cpp文件,輸入下面的代碼:
            >>
            #i nclude <stdio.h>
            void main()
            {
            int i=10;
            int a = i;
            printf("i= %d",a);
            //下面匯編語句的作用就是改變內存中i的值,但是又不讓編譯器知道
            __asm {
            mov dword ptr [ebp-4], 20h
            }
            int b = i;
            printf("i= %d",b);
            }      
            然后,在調試版本模式運行程序,輸出結果如下:
            i = 10
            i = 32
            然后,在release版本模式運行程序,輸出結果如下:
            i = 10
            i = 10
            輸出的結果明顯表明,release模式下,編譯器對代碼進行了優化,第二次沒有輸出正確的i值。下面,我們把 i的聲明加上volatile關鍵字,看看有什么變化:
            #i nclude <stdio.h>
            void main()
            {
            volatile int i=10;
            int a = i;
            printf("i= %d",a);
            __asm {
            mov dword ptr [ebp-4], 20h
            }
            int b = i;
            printf("i= %d",b);
            }      
            分別在調試版本和release版本運行程序,輸出都是:
            i = 10
            i = 32
            這說明這個關鍵字發揮了它的作用!

            -----------------------------------


            volatile對應的變量可能在你的程序本身不知道的情況下發生改變
            比如多線程的程序,共同訪問的內存當中,多個程序都可以操縱這個變量
            你自己的程序,是無法判定合適這個變量會發生變化
            還比如,他和一個外部設備的某個狀態對應,當外部設備發生操作的時候,通過驅動程序和中斷事件,系統改變了這個變量的數值,而你的程序并不知道。
            對于volatile類型的變量,系統每次用到他的時候都是直接從對應的內存當中提取,而不會利用cache當中的原有數值,以適應它的未知何時會發生的變化,系統對這種變量的處理不會做優化——顯然也是因為它的數值隨時都可能變化的情況。

            --------------------------------------------------------------------------------

            典型的例子
            for ( int i=0; i<100000; i++);
            這個語句用來測試空循環的速度的
            但是編譯器肯定要把它優化掉,根本就不執行
            如果你寫成  
            for ( volatile int i=0; i<100000; i++);
            它就會執行了

            volatile的本意是“易變的”  
            由于訪問寄存器的速度要快過RAM,所以編譯器一般都會作減少存取外部RAM的優化。比如:

            static int i=0;

            int main(void)
            {
            ...
            while (1)
            {
            if (i) dosomething();
            }
            }

            /* Interrupt service routine. */
            void ISR_2(void)
            {
            i=1;
            }

            程序的本意是希望ISR_2中斷產生時,在main當中調用dosomething函數,但是,由于編譯器判斷在main函數里面沒有修改過i,因此
            可能只執行一次對從i到某寄存器的讀操作,然后每次if判斷都只使用這個寄存器里面的“i副本”,導致dosomething永遠也不會被
            調用。如果將將變量加上volatile修飾,則編譯器保證對此變量的讀寫操作都不會被優化(肯定執行)。此例中i也應該如此說明。

            一般說來,volatile用在如下的幾個地方:

            1、中斷服務程序中修改的供其它程序檢測的變量需要加volatile;

            2、多任務環境下各任務間共享的標志應該加volatile;

            3、存儲器映射的硬件寄存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義;

            另外,以上這幾種情況經常還要同時考慮數據的完整性(相互關聯的幾個標志讀了一半被打斷了重寫),在1中可以通過關中斷來實
            現,2中可以禁止任務調度,3中則只能依靠硬件的良好設計了。
            posted @ 2008-07-27 21:56 halCode 閱讀(327) | 評論 (0)編輯 收藏
            ???諸位,咱當電子工程師也是十余年了,不算有出息,環顧四周,也沒有看見幾個有出息的!回顧工程師生涯,感慨萬千,愿意講幾句掏心窩子的話,也算給咱們師弟師妹們提個醒,希望他們比咱們強!
            ?
            [1]好好規劃自己的路,不要跟著感覺走!根據個人的理想決策安排,絕大部分人并不指望成為什么院士或教授,而是希望活得滋潤一些,爽一些。那么,就需要慎重安排自己的軌跡。從哪個行業入手,逐漸對該行業深入了解,不要頻繁跳槽,特別是不要為了一點工資而轉移陣地,從長遠看,這點錢根本不算什么,當你對一個行業有那么幾年的體會,以后錢根本不是問題。頻繁地動蕩不是上策,最后你對哪個行業都沒有摸透,永遠是新手!
            ?
            [2]可以做技術,切不可沉湎于技術。千萬不可一門心思鉆研技術!給自己很大壓力,如果你的心思全部放在這上面,那么注定你將成為孔乙己一類的人物!適可而止為之,因為技術只不過是你今后前途的支柱之一,而且還不是最大的支柱。
            ?
            [3]不要去做技術高手,只去做綜合素質高手!在企業里混,我們時常瞧不起某人,說他“什么都不懂,憑啥拿那么多錢,憑啥升官!”這是普遍的典型的工程師的迂腐之言。8051很牛嗎?人家能上去必然有他的本事,而且是你沒有的本事。你想想,老板搞經營那么多年,難道見識不如你這個新兵?人家或許善于管理,善于領會老板意圖,善于部門協調等等。因此務必培養自己多方面的能力,包括管理,親和力,察言觀色能力,攻關能力等,要成為綜合素質的高手,則前途無量,否則只能躲在角落看示波器!技術以外的技能才是更重要的本事!!從古到今,美國日本,一律如此!
            ?
            [4]多交社會三教九流的朋友!不要只和工程師交往,認為有共同語言,其實更重要的是和其他類人物交往,如果你希望有朝一日當老板或高層管理,那么你整日面對的就是這些人。了解他們的經歷,思維習慣,愛好,學習他們處理問題的模式,了解社會各個角落的現象和問題,這是以后發展的巨大的本錢。
            ?
            [6]抓住時機向技術管理或市場銷售方面的轉變!要想有前途就不能一直搞開發,適當時候要轉變為管理或銷售,前途會更大,以前搞技術也沒有白搞,以后還用得著。搞管理可以培養自己的領導能力,搞銷售可以培養自己的市場概念和思維,同時為自己以后發展積累龐大的人脈!應該說這才是前途的真正支柱!
            ?
            [7]逐漸克服自己的心里弱點和性格缺陷!多疑,敏感,天真(貶義,并不可愛),猶豫不決,膽怯,多慮,臉皮太薄,心不夠黑,教條式思維。。。這些工程師普遍存在的性格弱點必須改變!很難嗎?只在床上想一想當然不可能,去幫朋友守一個月地攤,包準有效果,去實踐,而不要只想!不克服這些缺點,一切不可能,甚至連項目經理都當不好--盡管你可能技術不錯!
            ?
            [8]工作的同時要為以后做準備!建立自己的工作環境!及早為自己配置一個工作環境,裝備電腦,示波器(可以買個二手的),仿真器,編程器等,業余可以接點活,一方面接觸市場,培養市場感覺,同時也積累資金,更重要的是準備自己的產品,咱搞技術的沒有錢,只有技術,技術的代表不是學歷和證書,而是產品,拿出象樣的產品,就可技術轉讓或與人合作搞企業!先把東西準備好,等待機會,否則,有了機會也抓不住!
            ?
            [9]要學會善于推銷自己!不僅要能干,還要能說,能寫,善于利用一切機會推銷自己,樹立自己的品牌形象,很必要!要創造條件讓別人了解自己,不然老板怎么知道你能干?外面的投資人怎么相信你?提早把自己推銷出去,機會自然會來找你!搞個個人主頁是個好注意!!特別是培養自己在行業的名氣,有了名氣,高薪機會自不在話下,更重要的是有合作的機會......

            [10]該出手時便出手!永遠不可能有100%把握!!!條件差不多就要大膽去干,去闖出自己的事業,不要猶豫,不要彷徨,干了不一定成功,但至少為下一次沖擊積累了經驗,不干永遠沒出息,而且要干成必然要經歷失敗。不經歷風雨,怎么見彩虹,沒有人能隨隨便便成功!
            posted @ 2006-04-11 10:51 halCode 閱讀(536) | 評論 (2)編輯 收藏

            借用別人的流程圖提醒自己編程的步驟


            1.面向連接的套接字的系統調用時序圖



            無連接協議的套接字調用時序圖

            面向連接的應用程序流程圖



            posted @ 2006-03-23 21:11 halCode 閱讀(6335) | 評論 (0)編輯 收藏
            大學生=吃飯+睡覺+談戀愛
            豬=吃飯+睡覺
            所以:大學生=豬+談戀愛
            以上推出 大學生-談戀愛=豬
            即 大學生不談戀愛的都是豬?
            同理得出 豬只要談戀愛就可以變成大學生
            posted @ 2006-03-21 10:34 halCode 閱讀(387) | 評論 (0)編輯 收藏

            李安獲最佳導演獎“首先要感謝很多在場和不在場的人,像制作人Ann Li,編劇Diana,Jack~~我覺得《斷背山》是屬于我李安一個人的,如果被其他人拍了,我將會很生氣!這部電影既不是關于同性戀,女人,愛情,而是愛的本身。
            謝謝大家的支持,謝謝我的妻子和兒子,我愛你們,我將永遠和你們同在。雖然在期間我的父親不幸過世,但是要感謝我家中的媽媽,還有中國臺灣,香港和內地的同胞們。最后,謝謝大家的關心!”

            看到這段話時,我十分感動,尤其是“但是要感謝我家中的媽媽,還有中國臺灣,香港和內地的同胞們。”體現了一種難得的親情,而且在拿到國際電影上最高榮譽的獎項時,不忘記自己是名中國人,不忘記把臺灣說成“中國臺灣”。

            然而我注意到這句話的表述有點怪怪的,是不是他自己的原話呢?我最不愿意懷疑的就是“中國臺灣”幾個字。于是我查看了sohu這段新聞下網友的評論,發現原文是這樣的:“And finally, to my mother and family, and everybody in Taiwan, Hong Kong and China. Thank you. ”,他說的是“臺灣、香港和中國”。。。。。

            盡管他是所有華人的驕傲,盡管也許他并沒有太在意他的表述,但是。。我多少還是有些失望的。。。。

            posted @ 2006-03-06 19:59 halCode 閱讀(689) | 評論 (0)編輯 收藏
            昨天寫了MoveWindow函數,今天又要寫SetWindowPos函數,因為MoveWindow確實不好,浪費了差不多一天時間。。。對于主窗口,選擇了Center屬性就可以移動位置,不選就不行;窗口資源過大也不能移動;改變后窗口的尺寸大于等于屏幕尺寸的話,在它上面DoModal出來的新窗口不能移動。。原來,使用MoveWindow移動對話框位置似乎有很苛刻的條件,一不小心就原地不動了,而且我也實在琢磨不透這樣的條件,網上也沒有查處來。今天用了SetWindowPos后,才發現,果然好用!

            BOOL SetWindowPos(
               
            const CWnd* pWndInsertAfter,
               
            int x,
               
            int y,
               
            int cx,
               
            int cy,
               UINT nFlags 
            );

            Parameters

            pWndInsertAfter
            Identifies the CWnd object that will precede this CWnd object in the Z-order. This parameter can be a pointer to a CWnd or a Pointer to one of the following values:
            • wndBottom   Places the window at the bottom of the Z-order. If this CWnd is a topmost window, the window loses its topmost status; the system places the window at the bottom of all other windows.
            • wndTop   Places the window at the top of the Z-order.
            • wndTopMost   Places the window above all nontopmost windows. The window maintains its topmost position even when it is deactivated.
            • wndNoTopMost   Repositions the window to the top of all nontopmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a nontopmost window.
            nFlags
            Specifies sizing and positioning options. This parameter can be a combination of the following: 常用的是SWP_SHOWWINDOW

            注意:
                這里的坐標參數用的是Client坐標,對于子窗口用的是其父窗口的坐標系。然而對于用DoModal()彈出的窗口,如果在資源屬性里沒有選擇Child屬性的話,它的父窗口是DeskTop,而不是調用DoModal()的窗口。

            posted @ 2006-03-01 17:30 halCode 閱讀(2726) | 評論 (0)編輯 收藏

            剛做的那個軟件界面很重要,就象是把自己做的一個個控件網上畫一樣,還要按照實際運行效果來不斷調整位置,很麻煩。當時使用MoveWindow()這個函數來控制對話框的大小和位置,不了解參數情況,在網上查了,記得好象放在這里備忘,那時還覺得blog真是方便。結果現在又要用起這個函數卻又找不到了!不知道是不是放在這個blog里了。看來blog多了還不方便了。不過不要誤會,那些都是以前找到這個blog之前暫時用的,都不太滿意。最后覺得還是這里好,hoho,方便。暈,我來寫這篇日志是干嗎的?這么扯到這么遠了。。。不說了,還是把MoveWindow()再貼一下吧。。

            BOOL MoveWindow
            (   HWND hWnd,      
            //Handle to the window
                int X,                      //Specifies the new position of the left side of the window.
                int Y,                      //Specifies the new position of the top of the window.
                int nWidth,
                
            int nHeight,
                BOOL bRepaint
            );

            這個是 API函數,如果在MFC中使用CWnd::MoveWindow則不需要第一個參數句柄hWnd,其他相同。
            posted @ 2006-02-28 15:44 halCode 閱讀(2896) | 評論 (0)編輯 收藏
            成功的人要具備:有肚量去容忍那些不能改變的事,有勇氣去改變那些可能改變的事,有智慧去區別上述兩類事。
            posted @ 2005-12-29 14:17 halCode 閱讀(331) | 評論 (0)編輯 收藏
            有些東西在你沒有遇到之前還真是不知道自己沒有弄清楚,也許是我平時細節的地方注意少了,看來以后要多加注意了。

            char *pStr;
            char ch;
            char str[] = "Hello";

            ch 
            = str[1];
            *pStr = str[1];

            printf(
            "ch = %c\n", ch);
            printf(
            "*pStr = %c"*pStr);

            此時打印ch值的時候能正確輸出,但是打印pStr[0]的時候就出問題了,跟蹤發現是pStr[0] = str[1];這句出現問題。

            原來,char *pStr; 只定義了一個4字節的指針變量,而這個變量里面的內容是將要指向一個char類型變量的,但是此時pStr只是個“野指針”,并沒有指向一個char類型的內存單元,所以,當用*pStr來訪問這個元素時,系統根本不知道該訪問何處的空間,因此,在使用pStr前,必須讓它指向一個具體的空間。

            由上面可以將相關語句改為
            char *pStr;
            char ch;
            char str[] = "Hello";

            pStr 
            = &ch;    //pStr指向ch、獲得初始化
            pStr = &str[1];  //pStr指向str[1]地址、獲得初始化
            ch = str[1];
            *pStr = str[1];

            printf(
            "ch = %c\n", ch);
            printf(
            "*pStr = %c"*pStr);
            也就是說,要先給指針一個地址值初始化它,然后才能用*訪問它指向的內容。



            ◎另外,在子函數中使用malloc()/new()分配的內存空間不會因子函數的返回而消失,函數只會清理調子函數里定義的變量的空間,如:
            char* func()
            {
              
            char *p;
              p 
            = (char *)malloc(sizeof(char));
              
              
            return p;
            }
              //返回后,p所在空間被釋放,但是p所指空間還存在
            所以,可以用p1=func();來獲得在func()中分配的空間。

            此中方法可以用來解決“指針的指針”使用不方便的問題。步驟分2步:1、把傳入的指針的指針參數去掉;2、把函數的返回值賦給要改變的對象的指針:
            void GetMemory2(char **p, int num)
            {
              
            *= (char *)malloc(sizeof(char* num);
            }

            void Test2(void)
            {
              
            char *str = NULL;
              GetMemory2(
            &str, 100);   // 注意參數是 &str,而不是str
              strcpy(str, "hello");    
              cout
            << str << endl;
              free(str);    
            }


            //////下面是用傳遞動態內存的方法實現
            char *GetMemory3(int num)
            {
              
            char *= (char *)malloc(sizeof(char* num);
              
            return p;
            }

            void Test3(void)
            {
              
            char *str = NULL;
              str 
            = GetMemory3(100);    
              strcpy(str, 
            "hello");
              cout
            << str << endl;
              free(str);    
            }

            因為此時用malloc/new分配的內存空間是堆里面的,函數返回時不會回收;而如果在子函數中用char p[]="asdfgewq";則p是在棧中定義的(先分配p的空間,然后講字符串拷貝進去,跟char *p="asdfasdf"分配在全局靜態內存中不一樣),所以會被系統收回。
            posted @ 2005-12-21 10:55 halCode 閱讀(572) | 評論 (0)編輯 收藏
            1。定義數組變量時必須指定數組元素個數,因為系統會根據元素個數在編譯時一次性分配這么多內存;
                  而指針變量只需要指定類型,系統只為該指針變量分配4字節(32位機)內存,而不會為該變量所指內容分配內存。

            2。指針變量是有存儲空間的;而數組名僅僅是一個標號,沒有實際存儲空間,單單一個數組名就只能表示該數組的第1個元素的地址。int a[10]; 規定&a就等于&a[0]或者a .

            3。例如 char str[]= "hello world"和char *p = "hello world"中,數組str是先分配給他元素個數個內存,然后將后面的字符串復制給這個空間(注意,此時應該考慮\0字符);而p的建立過程是先在靜態存儲區建立常字符串"hello world\0",然后將p指向這個常字符串。所以數組str中元素的內容可以通過重新賦值改變,而p指向的內容不能改變。
            posted @ 2005-12-18 21:40 halCode 閱讀(560) | 評論 (0)編輯 收藏
            僅列出標題  下一頁

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(7)

            隨筆分類

            隨筆檔案

            文章分類

            文章檔案

            相冊

            編程資源

            不務正業

            找工作

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲午夜无码久久久久小说| 9999国产精品欧美久久久久久| 欧美粉嫩小泬久久久久久久| 久久久精品国产Sm最大网站| 久久免费视频1| 91久久九九无码成人网站| 无码任你躁久久久久久久| 亚洲综合日韩久久成人AV| 国产精品美女久久久久AV福利 | 成人久久综合网| 欧洲国产伦久久久久久久| 久久久久人妻一区精品色| 婷婷久久综合九色综合九七| 久久精品毛片免费观看| 人人狠狠综合久久亚洲| 久久精品国产福利国产秒| 2019久久久高清456| 国内精品久久久久久久亚洲| 欧美黑人激情性久久| 欧美黑人激情性久久| 91精品国产91热久久久久福利| 亚洲综合精品香蕉久久网| 日韩AV毛片精品久久久| 精品久久人人妻人人做精品| 国产成人久久AV免费| 中文字幕久久精品无码| 四虎影视久久久免费观看| 国产精品无码久久久久| 精品国产91久久久久久久| 久久久av波多野一区二区| 亚洲精品国精品久久99热一| 久久精品国产2020| 久久国产劲爆AV内射—百度| 久久精品国产2020| 亚洲va久久久噜噜噜久久| av色综合久久天堂av色综合在| 久久伊人精品一区二区三区| 欧美日韩精品久久久免费观看| 久久国产色av免费看| 日韩久久久久久中文人妻| 国产精品久久久久jk制服|