<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C語言指針易混淆知識點總結

      指針

      定義

      指針是一個變量,存儲另一個變量的內存地址,它允許直接訪問和操作內存中的數據,使得程序能夠以更靈活和高效的方式處理數據和內存。

      獲取變量地址:使用取地址符 &

      訪問地址上的數據:使用解引用符 *

      例子1

      指針是存儲另一個變量地址的變量。通過使用取地址符 & 和解引用符 *,我們可以靈活地訪問和操作內存中的數據 。

      #include <stdio.h>
      
      int main() {
          int var = 10;     // 定義一個整數變量
          int *p = &var;    // 定義一個指向整數的指針,并將其初始化為變量 var 的地址
      
          printf("Address of var: %p\n", &var); // 輸出變量 var 的地址
          printf("Address stored in pointer p: %p\n", p); // 輸出指針 p 中存儲的地址
          printf("Value of var using pointer: %d\n", *p); // 通過指針 p 解引用獲取 var 的值
      
          // 修改 var 的值,通過指針 p
          *p = 20;
          printf("New value of var: %d\n", var); // 輸出修改后的 var 的值
      
          return 0;
      }
      

      例子2

      指針類型決定了它指向的變量類型,以及通過指針可以訪問的數據大小。不同類型的指針在操作時會有不同的步長,比如:

      int *p = (int *)a;:將 char 類型數組的首地址強制轉換為 int 指針類型。由于 int 類型通常占用 4 個字節,因此通過 p 訪問數據時,每次會讀取 4 個字節的數據。

      char *q = a;:將 char 類型數組的首地址賦值給 char 指針類型。char 類型占用 1 個字節,因此通過 q 訪問數據時,每次只會讀取 1 個字節的數據。

      #include <stdio.h>
      
      int main() {
          char a[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C};
          int *p = (int *)a; // 將 char 數組的地址賦值給 int 指針
          char *q = a;       // 將 char 數組的地址賦值給 char 指針
          
          // 使用 int 指針訪問數據
          printf("Using int pointer:\n");
          for (int i = 0; i < 3; i++) {
              printf("p[%d]: 0x%08x\n", i, *(p + i));
          }
          
          // 使用 char 指針訪問數據
          printf("Using char pointer:\n");
          for (int i = 0; i < 12; i++) {
              printf("q[%d]: 0x%02x\n", i, *(q + i));
          }
      
          return 0;
      }
      
      /*
      輸出
      Using int pointer:
      p[0]: 0x04030201
      p[1]: 0x08070605
      p[2]: 0x0c0b0a09
      
      Using char pointer:
      q[0]: 0x01
      q[1]: 0x02
      q[2]: 0x03
      q[3]: 0x04
      q[4]: 0x05
      q[5]: 0x06
      q[6]: 0x07
      q[7]: 0x08
      q[8]: 0x09
      q[9]: 0x0a
      q[10]: 0x0b
      q[11]: 0x0c
      */
      

      一級指針和二級指針

      一級地址(一級指針)

      定義

      一級地址指的是指向普通變量的指針,也就是直接存儲變量的地址的指針。在C中,通常我們操作的是一級地址,例如指向整數、浮點數或其他基本數據類型的指針。

      例子

      int *ptr;  // ptr 是一個指向整數的指針,是一級地址
      float *ptr_float;  // ptr_float 是一個指向浮點數的指針,也是一級地址
      

      二級地址(二級指針)

      定義

      二級地址是指向指針的指針,也就是存儲另一個指針的地址的指針。在C中,可以通過二級指針來操作指向指針的指針,用來間接修改指針指向的值或者傳遞指針的引用。

      例子

      int x = 10;
      int *ptr1 = &x;  // ptr1 是一個指向 x 的指針,是一級地址
      int **ptr2 = &ptr1;  // ptr2 是一個指向 ptr1 的指針,是二級地址
      

      例子

      分析表達式 *(*(&arr + 1) - 1) 的值:

      int arr[5] = {1, 2, 3, 4, 5};
      
      1. arr[5] = {1, 2, 3, 4, 5}:這定義了一個包含 5 個整數的數組 arr,其元素分別是 {1, 2, 3, 4, 5}
      2. &arr:這是數組 arr 的地址。需要注意的是,&arr 的類型是 int (*)[5],即指向一個包含 5 個整數的數組的指針。
      3. &arr + 1:這是 &arr 指針加 1。在這個上下文中,&arr 被看作是一個指向整個數組的指針,因此 &arr + 1 將指向緊隨 arr 之后的內存位置。也就是說,它指向 arr 后面的內存地址,而不是數組中的下一個元素。&arr + 1 的類型仍然是 int (*)[5]
      4. *(&arr + 1):這是對 &arr + 1 解引用。&arr + 1 是一個指向數組的指針,對其解引用后,得到的仍然是一個指向數組末尾之后的指針。它的類型是 int *,即指向數組末尾之后的指針。
      5. *(&arr + 1) - 1:這將剛才得到的指針減去 1。由于指針的減法是以元素為單位的,這個操作將指針向后移動一個 int 的大小。因為 *(&arr + 1) 指向的是數組 arr 末尾之后的位置,減去 1 后,這個指針將指向數組 arr 的最后一個元素。
      6. *(*(&arr + 1) - 1):最后,對指針 *(&arr + 1) - 1 解引用,即獲取這個指針所指向的值。這個指針現在指向 arr 的最后一個元素,所以這個表達式的值就是 arr 的最后一個元素的值。

      因此,*(*(&arr + 1) - 1) 的值是 5,即數組 arr 的最后一個元素。

      指針的自增運算

      *++p

      這個表達式是先對指針 p 進行自增操作,然后對新的指針進行解引用,得到新的指針所指向的值。

      步驟

      1. ++p:指針 p 先自增,指向下一個元素( 自增的是指針 )。
      2. *:對自增后的指針解引用,得到新指針所指向的值。

      ++*p

      這個表達式是對指針 p 所指向的值進行解引用,然后對解引用得到的值進行自增操作。

      步驟

      1. *p:對指針 p 進行解引用,得到指向的值。
      2. ++:對解引用得到的值進行自增操作( 自增的是指針指向的值 )。

      函數地址與數組地址

      函數地址

      函數名就是函數的入口地址,因此可以直接把函數名賦給函數指針,也可以加上取地址符號 &。取地址符號 & 是可選的,它只是顯式地說明了編譯器隱式執行的任務。獲取函數的地址時,加不加取地址符號 & 都可以

      #include <stdio.h>
      
      int test(int i) {
          return i;
      }
      
      int main(void) {
          int (*p1)(int) = test;
          int (*p2)(int) = &test;
          printf("%p, %p\n", (void *)p1, (void *)p2);
          return 0;
      }
      

      數組地址

      數組名本身是數組第一個元素的地址。例如,對于 int 類型的數組來說,數組名 arr 的類型是 int*,它是一個整型指針,不是數組指針。如果要取整個數組的地址,必須在數組名前面加上取地址符號 &,這樣才能賦值給數組指針。獲取數組的地址時,必須加上取地址符號 &

      在下面的例子中, p1 是一個整型指針,指向數組的第一個元素,而 p2 是一個數組指針,指向整個數組。對 p1p2 分別進行加 1 操作,p1 會加 4 個字節(假設 int 為 4 字節),而 p2 會加 20 個字節(5 個 int)。

      #include <stdio.h>
      
      int main(void) {
          int array[5] = {1, 2, 3, 4, 5};
          int* p1 = array;         // 指向數組第一個元素
          int(*p2)[5] = &array;    // 指向整個數組
          printf("p1 %p\n", (void*)p1);
          printf("p2 %p\n", (void*)p2);
          printf("p1+1 %p\n", (void*)(p1+1));  // p1 加 1,增加 4 個字節(假設 int 為 4 字節)
          printf("p2+1 %p\n", (void*)(p2+1));  // p2 加 1,增加 20 個字節(5 個 int)
          return 0;
      }
      

      指針和數組

      不需要嚴格區分的情況

      訪問數組元素

      對于數組和指針,都可以使用下標形式或指針形式來訪問元素。

      #include <stdio.h>
      
      int main(void) {
          char array[] = "hello world!";
          char* p = array;
      
          array[1] = 'x';      // 使用下標訪問數組
          *(array + 1) = 'x';  // 使用指針形式訪問數組
      
          p[1] = 'y';          // 使用下標訪問指針
          *(p + 1) = 'y';      // 使用指針形式訪問指針
      
          printf("%s\n", array); // 輸出: hyllo world!
          printf("%s\n", p);     // 輸出: hyllo world!
      
          return 0;
      }
      

      作為函數參數傳遞

      實參傳遞數組時,形參可以是數組或指針。實參傳遞指針時,形參也可以是數組或指針。編譯器會將數組參數退化為指針。

      #include <stdio.h>
      
      void printArray(int arr[], int size) {
          for (int i = 0; i < size; i++) {
              printf("%d ", arr[i]);
          }
          printf("\n");
      }
      
      int main(void) {
          int array[] = {1, 2, 3, 4, 5};
          printArray(array, 5); // 傳遞數組
          return 0;
      }
      

      需要嚴格區分的情況

      使用 sizeof 計算長度

      sizeof(array) 返回數組的字節數。sizeof(pointer) 返回指針的大小(在64位系統中為8字節,在32位系統中為4字節)。

      #include <stdio.h>
      
      int main(void) {
          char array[] = "hello world!";
          char* p = array;
      
          printf("sizeof(array) = %lu\n", sizeof(array)); // 輸出: 13
          printf("sizeof(p) = %lu\n", sizeof(p));         // 輸出: 8 (在64位系統中)
      
          return 0;
      }
      

      計算數組長度

      當數組作為參數傳遞時,在函數內部不能使用 sizeof 計算數組長度,因為數組會退化為指針。

      #include <stdio.h>
      
      void test(int arg[]) {
          printf("sizeof(arg) = %lu\n", sizeof(arg)); // 輸出指針大小,例如在64位系統中為8
      }
      
      int main(void) {
          int array[10];
          test(array); // 傳遞數組
          return 0;
      }
      

      聲明外部變量

      在一個文件中定義指針 p,在另一個文件中不能聲明為數組。

      //file1.c:
      
      int* p;
      
      // file2.c
      
      extern int* p; // 正確:聲明為指針
      // extern int p[]; // 錯誤:不能聲明為數組
      

      指針常量和常量指針

      指針常量

      定義

      不能改變指向的指針。也就是說,一旦初始化后,就不能再改變指向其它地址,但可以修改指針所指向地址上的內容。

      例子

      比如指針 p,因為它被 const 修飾,所以 p 不能被修改,它只能指向 str。如果強行對 p 進行 p++ 操作,編譯時就會報錯。我們稱指針 p 為指針常量。盡管 p 本身不能被修改,但可以通過 p 來修改 str 的內容,例如 *p = 'H';

      char str[] = "hello world!";
      char *const p = str;
      

      常量指針

      定義

      不能改變所指向的值的指針。也就是說,通過這個指針不能修改它所指向的值,但可以修改指針的指向。

      例子

      p 是一個指向 char 類型常量的指針。可以修改 p 的指向,例如 p = another_str;,但不能通過 p 修改其指向的內容,例如 *p = 'H'; 是不允許的。

      const char *p = "hello world!";
      char const *p = "hello world!";
      

      指針數組和數組指針

      指針數組

      定義

      本質是一個數組,數組的每個元素都是指針。

      例子1

      int *p[4]; 這一聲明中,p 先與中括號結合,表示 p 是一個有四個元素的數組,每個元素的類型都是 int *(指向整型的指針)。因此,我們稱 p 為指針數組。

      int *p[4];
      

      例子2

      int a = 1, b = 2, c = 3, d = 4;
      int *p[4] = { &a, &b, &c, &d };
      
      for (int i = 0; i < 4; i++) {
          printf("%d ", *p[i]);
      }
      // 輸出:1 2 3 4
      

      數組指針

      定義

      本質是一個指針,指向一個數組。

      例子1

      int (*p)[4]; 這一聲明中,p 先與 * 結合,表示 p 是一個指針,然后與中括號結合,表示 p 指向一個有四個元素的數組,每個元素的類型都是 int。因此,我們稱 p 為數組指針。

      int (*p)[4];
      

      例子2

      int arr[4] = {1, 2, 3, 4};
      int (*p)[4] = &arr;
      
      for (int i = 0; i < 4; i++) {
          printf("%d ", (*p)[i]);
      }
      // 輸出:1 2 3 4
      

      函數指針和指針函數

      函數指針

      定義

      本質是一個指針,指向一個函數。每個函數在內存中都有一個地址,函數調用就是跳轉到這個地址開始執行,函數指針記錄了這個地址的變量。

      例子

      p 是一個指針,指向一個函數,該函數有一個 int 類型的參數,返回值是 int可以通過函數名 test(1) 來調用函數,也可以通過指針 p 來調用 p(1)或者(*p)(1)

      #include <stdio.h>
      
      int test(int i) {
          return i;
      }
      
      int main(void) {
          int res = 0;
          int (*p)(int) = test;
          res = test(1);
          printf("%d\n", res);
          res = p(1);
          printf("%d\n", res);
          res = (*p)(1);
          printf("%d\n", res);
          return 0;
      }
      

      應用

      往結構體中放入函數

      C語言的結構體不支持成員函數,但可以通過函數指針實現類似的功能。結構體中可以定義一個函數指針,用來保存函數地址。函數名可以直接賦值給函數指針。C語言的結構體在使用時必須加上 struct 關鍵字,而 C++ 可以省略。

      #include <stdio.h>
      #include <stdlib.h>
      
      // 定義一個打印函數
      void print(int a, int b) {
          printf("%d %d\n", a, b);
      }
      
      // 定義一個結構體,其中包含一個函數指針
      struct Test {
          void (*p)(int, int);
      };
      
      int main(void) {
          // 動態分配結構體內存
          struct Test* t = (struct Test *)malloc(sizeof(struct Test));
          if (t == NULL) {
              fprintf(stderr, "Memory allocation failed\n");
              return 1;
          }
          
          // 將函數指針指向打印函數
          t->p = print;
          
          // 調用函數指針
          t->p(3, 4); // 輸出: 3 4
          
          // 釋放動態分配的內存
          free(t);
          
          return 0;
      }
      

      回調函數

      是一種通過函數指針實現的技術,允許在一個函數中調用另一個函數。通常用于事件驅動編程或處理異步操作。

      #include <stdio.h>
      
      // 定義一個回調函數類型
      typedef void (*Callback)(int);
      
      // 定義一個回調函數
      void myCallback(int value) {
          printf("Callback called with value: %d\n", value);
      }
      
      // 定義一個執行操作并調用回調函數的函數
      void performOperation(int x, Callback callback) {
          printf("Performing operation with value: %d\n", x);
          // 調用回調函數
          callback(x);
      }
      
      int main(void) {
          // 使用回調函數
          performOperation(5, myCallback);
          return 0;
      }
      

      動態函數調用

      在需要根據某些條件動態選擇和調用不同函數時,函數指針非常有用。例如,在一個計算器程序中可以動態選擇不同的操作函數。

      #include <stdio.h>
      
      // 定義操作函數
      int add(int a, int b) { return a + b; }
      int subtract(int a, int b) { return a - b; }
      int multiply(int a, int b) { return a * b; }
      int divide(int a, int b) { return a / b; }
      
      int main(void) {
          // 定義一個函數指針數組
          int (*operations[4])(int, int) = { add, subtract, multiply, divide };
          
          int a = 10, b = 5;
          char op = '+';
      
          // 根據操作符選擇對應的函數
          int (*operation)(int, int) = NULL;
          switch (op) {
              case '+': operation = operations[0]; break;
              case '-': operation = operations[1]; break;
              case '*': operation = operations[2]; break;
              case '/': operation = operations[3]; break;
          }
      
          if (operation != NULL) {
              printf("Result: %d\n", operation(a, b));
          } else {
              printf("Invalid operation\n");
          }
      
          return 0;
      }
      

      實現多態行為

      通過函數指針數組,可以在C語言中實現類似C++的多態行為。這種技術廣泛應用于設計模式和框架中。

      #include <stdio.h>
      
      // 定義一個基類結構體
      struct Shape {
          void (*draw)(struct Shape*);
      };
      
      // 定義一個派生類結構體
      struct Circle {
          struct Shape base; // 基類
          int radius;
      };
      
      // 定義一個繪制函數
      void drawCircle(struct Shape* shape) {
          struct Circle* circle = (struct Circle*)shape;
          printf("Drawing a circle with radius: %d\n", circle->radius);
      }
      
      int main(void) {
          // 創建一個 Circle 對象
          struct Circle c;
          c.base.draw = drawCircle;
          c.radius = 5;
      
          // 調用繪制函數
          c.base.draw((struct Shape*)&c);
      
          return 0;
      }
      

      實現狀態機

      是一種在不同狀態之間轉換的編程模式。可以通過函數指針實現狀態之間的動態切換。

      #include <stdio.h>
      
      // 定義狀態函數類型
      typedef void (*StateFunction)();
      
      // 定義狀態函數
      void stateA() {
          printf("State A\n");
      }
      void stateB() {
          printf("State B\n");
      }
      void stateC() {
          printf("State C\n");
      }
      
      int main(void) {
          // 定義一個狀態函數指針數組
          StateFunction states[3] = { stateA, stateB, stateC };
          
          int currentState = 0;
          for (int i = 0; i < 5; i++) {
              // 調用當前狀態函數
              states[currentState]();
              // 切換到下一個狀態
              currentState = (currentState + 1) % 3;
          }
      
          return 0;
      }
      

      代碼跳轉到指定位置執行

      比如((void(*)())0)();代表讓程序跳轉到地址為0的地方去運行。

      解析步驟

      1. (void (*)()):這是一個類型轉換,表示一個指向返回類型為 void、無參數的函數的指針。具體來說,void (*)() 是一種函數指針類型,它指向的函數沒有參數并返回 void
      2. 0:這是一個整數常量 0。在C中,可以將整數常量 0 作為空指針常量。
      3. (void (*)())0:這將整數 0 轉換為類型為 void (*)() 的函數指針。換句話說,這是將 0 解釋為一個指向無參數、返回類型為 void 的函數的指針。
      4. ((void (*)())0):這只是對前面步驟的類型轉換進行一次包裹,結果仍然是一個類型為 void (*)() 的函數指針,指向 0 地址。
      5. ((void (*)())0)():這表示對 0 地址的函數指針進行調用。具體來說,這是試圖調用位于地址 0 處的函數。

      指針函數

      定義

      本質是一個函數,其返回值是一個指針。

      例子

      錯誤示例

      下面這個例子是一個典型的錯誤,因為不能返回一個局部變量的地址。函數調用完畢后,局部變量的內存會被釋放,即使返回了這個地址也不能使用。

      int* test() {
          int array[5] = {0};  // 局部變量
          return array;  // 錯誤:返回局部變量的地址
      }
      
      int main(void) {
          int* p = test();  // 不安全
          return 0;
      }
      

      返回堆空間地址

      #include <stdio.h>
      #include <stdlib.h>
      
      int* test() {
          int* array = (int*)malloc(sizeof(int) * 5);  // 動態分配堆空間
          if (array != NULL) {
              for (int i = 0; i < 5; ++i) {
                  array[i] = i;  // 初始化數組
              }
          }
          return array;  // 返回堆空間地址
      }
      
      int main(void) {
          int* p = test();
          if (p != NULL) {
              for (int i = 0; i < 5; ++i) {
                  printf("%d ", p[i]);  // 輸出:0 1 2 3 4
              }
              free(p);  // 釋放動態分配的內存
          }
          return 0;
      }
      

      返回全局變量地址

      #include <stdio.h>
      
      int array[5];  // 全局變量
      
      int* test() {
          for (int i = 0; i < 5; ++i) {
              array[i] = i;  // 初始化數組
          }
          return array;  // 返回全局變量地址
      }
      
      int main(void) {
          int* p = test();
          for (int i = 0; i < 5; ++i) {
              printf("%d ", p[i]);  // 輸出:0 1 2 3 4
          }
          return 0;
      }
      

      返回靜態變量地址

      #include <stdio.h>
      
      int* test() {
          static int array[5];  // 靜態變量
          for (int i = 0; i < 5; ++i) {
              array[i] = i;  // 初始化數組
          }
          return array;  // 返回靜態變量地址
      }
      
      int main(void) {
          int* p = test();
          for (int i = 0; i < 5; ++i) {
              printf("%d ", p[i]);  // 輸出:0 1 2 3 4
          }
          return 0;
      }
      

      指針函數指針

      定義

      是一個指向返回指針的函數的指針。它不僅是一個指向函數的指針,而且該函數返回的也是一個指針。

      例子

      #include <stdio.h>
      #include <stdlib.h>
      
      // 定義一個返回整數指針的函數
      int* allocateArray(int size) {
          int* array = (int*)malloc(size * sizeof(int));  // 動態分配內存
          if (array != NULL) {
              for (int i = 0; i < size; ++i) {
                  array[i] = i;  // 初始化數組
              }
          }
          return array;  // 返回堆空間地址
      }
      
      // 定義一個指向返回整數指針的函數的指針類型
      typedef int* (*ArrayAllocator)(int);
      
      int main(void) {
          // 定義一個指向返回整數指針的函數的指針
          ArrayAllocator allocator = allocateArray;
          
          int size = 5;
          // 使用指針函數指針調用函數
          int* array = allocator(size);
          if (array != NULL) {
              for (int i = 0; i < size; ++i) {
                  printf("%d ", array[i]);  // 輸出:0 1 2 3 4
              }
              printf("\n");
              free(array);  // 釋放動態分配的內存
          }
          return 0;
      }
      

      懸掛指針和野指針

      懸掛指針

      定義

      懸掛指針是指向已經釋放(通過 free 函數釋放)或者已經超出作用域的內存的指針。當我們試圖通過這樣的指針訪問或操作內存時,可能會導致未定義行為,因為那塊內存可能已經被操作系統重新分配給其它程序使用了。

      #include <stdio.h>
      #include <stdlib.h>
      
      void dangling_pointer_example() {
          int *p = (int *)malloc(sizeof(int));
          *p = 42;
          printf("Value: %d\n", *p); // 輸出42
      
          free(p); // 釋放內存
      
          // p現在是懸掛指針,訪問*p將導致未定義行為
          // printf("Value: %d\n", *p); // 不安全,可能導致崩潰或未定義行為
      }
      
      int main() {
          dangling_pointer_example();
          return 0;
      }
      

      解決方法

      立即將指針設為NULL:在釋放內存后,將指針設置為NULL。

      free(p);
      p = NULL;
      

      避免返回局部變量的指針:不要返回局部變量的指針,因為它們在函數返回后將超出作用域。

      int* incorrect_function() {
          int x = 42;
          return &x; // 返回局部變量的指針,錯誤
      }
      

      野指針

      定義

      野指針是一個未初始化的指針,它的值是未知的,可能指向任意內存地址。當我們試圖通過這樣的指針訪問或操作內存時,可能會導致未定義行為。

      #include <stdio.h>
      
      void wild_pointer_example() {
          int *p; // 未初始化的指針
          // *p = 42; // 不安全,可能導致崩潰或未定義行為
      }
      
      int main() {
          wild_pointer_example();
          return 0;
      }
      

      解決方法

      在聲明指針時初始化:聲明指針時將其初始化為NULL或有效地址。

      int *p = NULL;
      

      確保在使用前分配內存:在使用指針之前,確保它已經被正確初始化和分配內存。

      int *p = (int *)malloc(sizeof(int));
      if (p != NULL) {
          *p = 42;
      }
      
      posted @ 2024-07-22 21:35  大雄的叮當貓  閱讀(621)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 久久精品国产一区二区三| 真实单亲乱l仑对白视频| 亚洲中文字幕精品一区二区三区| 国产普通话刺激视频在线播放| 色欲久久久天天天综合网精品| 日本三级香港三级三级人妇久 | 国产永久免费高清在线观看| 少妇被无套内谢免费看| 国偷自产av一区二区三区| 亚洲 小说区 图片区 都市| 久久综合国产一区二区三区| 免费乱理伦片在线观看| 亚洲人成网站77777在线观看| 高清精品视频一区二区三区| 亚洲国产精品综合久久20| 色国产视频| 黄色亚洲一区二区在线观看| 日日碰狠狠添天天爽超碰97| 丝袜美腿亚洲综合在线观看视频 | 黑人巨茎大战白人美女| 加勒比中文字幕无码一区| 国产精品一级久久黄色片| 国产精品v欧美精品∨日韩| 国产欧美精品一区aⅴ影院| 久热这里只有精品蜜臀av| 久久青青草原精品国产app| 国产在线啪| 国产午夜福利视频一区二区| 亚洲国产精品一区二区视频| 少妇无套内谢免费视频| 国产精品一二三区久久狼| 亚洲欧美在线看片AI| 日韩av片无码一区二区不卡| 久热这里只有精品视频3| 人人妻人人添人人爽日韩欧美| 亚洲蜜臀av乱码久久| 日韩精品国内国产一区二| 亚洲男女羞羞无遮挡久久丫| 裸体美女无遮挡免费网站| 久久久久久亚洲精品成人| 毛片av在线尤物一区二区|