C語言基礎(chǔ)

數(shù)據(jù)類型

基本數(shù)據(jù)類型

  • java基本數(shù)據(jù)類型
  * byte 1個字節(jié)
  * short 2個字節(jié)
  * int 4個字節(jié)
  * long 8字節(jié)
  • 浮點型
  * float 4個字節(jié)
  * double 8字節(jié)
  • 字符型
  * char 2字節(jié)
  • boolean true/false

C的基本數(shù)據(jù)類型

  • 整型
  * short int
  * int
  * long int
  * long long int
  • 浮點型
  * float
  * double
  • 字符型
  * char

格式化輸出

  • short類型:
short a = 123; 
printf("%hd\n", a);
  • int類型
int b = 123;
printf("b = %d\n", b);
  • long 類型
long int c = 345;
printf("c = %ld", c);
  • long long 類型
long long d = 123456;
printf("d=%lld\n", d);
  • float 類型
float e = 1.234;
printf("e=%f\n", e);//默認6位有效數(shù)字
printf("e = %.2f\n", e);//保留兩位有效數(shù)字
  • double 類型
double f = 2.34567;
printf("f = %lf\n", f);//默認6位有效數(shù)字
printf("f = %.4lf\n", f);//保留四位有效數(shù)字
  • 字符類型
char g = 'a';
printf("g = %c\n", g);

各種數(shù)據(jù)類型在內(nèi)存中的大小

  • 判斷變量在內(nèi)存中的大小
int a = 12;
int size = sizeof(a);
printf("sizeof(int) = %d\n", size);
  • 基本數(shù)據(jù)類型在內(nèi)存中的大小
sizeof(int) = 4;
sizeof(short) = 2;
sizeof(long) = 4;
sizeof(long long) = 8;
sizeof(float) = 4;
sizeof(double) = 8;
sizeof(char) = 1;
  • 0為假, 非零為真。
if(0){//假
}else{
}

指針 直接操作內(nèi)存區(qū)域

  • 指針賦值和修改值
int a = 123;
int *p;
p = &a;//將a的地址取出來, 然后賦值給p
printf("a=%d\n",*p);
*p = 234;//將234賦值給指針p
printf("a=%d\n", a);
  • 交換兩個數(shù)的值
int a = 0;
int b = -1;
int *p1 = &a;
int *p2 = &b;
*p1 = *p1^*p2;
*p2 = *p1^*p2;
*p1 = *p1^*p2;
printf("a =%d, b = %d\n", a, b);
  • 多級指針
void test(){
    int a = 1;
    int *p1 = &a;//一級指針 
    int **p2 = &p1;//二級指針 
    int ***p3 = &p2;//三級指針 
    int ****p4 = &p3;//四級指針
    printf("*p1 = %d\n", *p1); 
    printf("**p2 = %d\n", **p2);
    printf("***p3 = %d\n", ***p3);
    printf("****p4 = %d\n", ****p4);
}
  • 函數(shù)指針
int add(int a, int b){
    return a+b;
} 
int minus(int a, int b){
        return a-b;
}
//指針當做函數(shù)參數(shù)
int compute(int a, int b, int(*pf)(int, int)){
    return pf(a, b);
}
void test2(){
    //定義函數(shù)指針變量p,p指向一個函數(shù), 
    //函數(shù)的返回值必須是int,  函數(shù)的形參 
    int (*p) (int, int);
    p = &add;
    p = −
    int result = p(2, 3);
    //使用方式一
    int result = compute(2, 3, p);
    //使用方式二
    result = compute(2, 3, &add);
    printf("result = %d\n", result);
     
}
  • 野指針 沒有任何指向的指針
int *p;
*p = 123;
printf("*p = %d\n", *p);

數(shù)組

  • 數(shù)組定義
void test3(){
    //數(shù)組定義 
    int arr1[10];
    int arr2[] = {1, 2, 3, 4, 5};
    int arr3[10] = {1, 2, 3};
    int len1 = sizeof(arr1)/sizeof(int);
    int len2 = sizeof(arr2)/sizeof(int);
    int len3 = sizeof(arr3)/sizeof(int); 
    printf("%d\n", len1); 
    printf("%d\n", len2); 
    printf("%d\n", len3); 
    
    for(int i=0; i<len2; i++){
        printf("arr2[i] = %d\n", arr2[i]);
    }
}
  • 數(shù)組的遍歷
void print_arr(int arr[], int len){
    for(int i=0; i<len; i++){
        printf("arr[%d] = %d\n", i, arr[i]);
    }   
} 

void print_arr2(int *p, int len){
    for(int i=0; i<len; i++){
        //通過索引取值 
        //printf("arr[%d] = %d\n", i, p[i]);
        //通過地址值取值 
        printf("arr[%d] = %d\n", i, *(p+i));
    }
}

void test4(){
    int arr[] = {1, 6, 3, 4, 67};
    int len = sizeof(arr) / sizeof(int);
    print_arr(arr, len);
    print_arr2(arr, len);
}
  • 數(shù)組的排序
void test5(){
    int arr[] = {1, 6, 3, 4, 67};
    int len = sizeof(arr)/sizeof(int);
    for(int i=0; i<len-1; i++){
        for(int j=0; j<len-1-i; j++){
            if(arr[j] > arr[j+1]){
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
    for(int k=0; k<len; k++){
        printf("arr[%d] = %d\n", k, arr[k]);
    }
} 
  • 內(nèi)存模型 linux環(huán)境下
    1. Text段
    2. data段
      stack
      heap
      static data//已經(jīng)初始化的常量或全局變量
    3. bss段 未初始化的常量和全局變量
  • 內(nèi)存申請和釋放 動態(tài)數(shù)組
#include <stdio.h>
#include <stdlib.h>
void test6(){
    int len = 3;
//  void* p = malloc(len*sizeof(int));
    //申請內(nèi)存 
    int *p1 =(int*) malloc(len*sizeof(int));
    p1[0] = 0;
    p1[1] = 1;
    p1[2] = 2;
    int i = 0;
    for(; i<len; i++){
        printf("p1[%d] = %d\n", i, p1[i]);
    }
    //釋放空間 
    free(p1);
}
int main(){
    test6();
}

結(jié)構(gòu)體

  • 結(jié)構(gòu)體定義方式
#include <stdio.h>
#include <stdlib.h>
//第一種定義方式 結(jié)構(gòu)體 
struct Student{
    char *name;
    int age;
    double score;
}; 
//第二種定義方式
struct Person{
    char *name;
    int age;
} person; 

//第三種定義方式 匿名結(jié)構(gòu)體 
struct {
    char *name;
    int age;
}; 

int main(){
    
    //結(jié)構(gòu)體賦值
    struct Student stu = {"張三", 23, 99.5};
    printf("stu.name = %s, stu.age=%d, stu.double=%.2lf\n", stu.name, stu.age, stu.score); 
     
    person.name = "wwf";
    person.age = 12;
    
    printf("name = %s, age = %d\n", person.name, person.age); 
}
  • 結(jié)構(gòu)體指針
struct Student{
    char *name;
    int age;
    double score;
}; 
int main(){
    //結(jié)構(gòu)體賦值
    struct Student stu = {"張三", 23, 99.5};
    struct Student *p = &stu;
    (*p).name = "龍飛";
    (*p).age = 99; 
    printf("stu.name = %s, stu.age=%d, stu.score=%.2lf\n", stu.name, stu.age, stu.score); 
    //間接引用運算符
    printf("stu.name = %s, stu.age = %d, stu.score = %.2lf\n", p->name, p->age, p->score); 
    //二級指針 
    struct Student **p2;
    p2 = &p; 
    printf("stu.name = %s, stu.age = %d, stu.score = %.2lf\n", (**p2).name, (**p2).age, (**p2).score);
    printf("stu.name = %s, stu.age = %d, stu.score = %.2lf\n", (*p2)->name, (*p2)->age, (*p2)->score);
}
  • 結(jié)構(gòu)體大小
內(nèi)存開辟為2的整數(shù)倍, 各個數(shù)據(jù)類型的大小之和
struct Student{
    char *name;//4byte 
    int age;//4byte
    double score;//8byte
}; 
大小為16byte
  • 結(jié)構(gòu)體中添加方法
int add(int a, int b){
    return a+b;
}
// 結(jié)構(gòu)體 
struct Student{
    char *name;//4byte 
    int age;//4byte
    double score;//8byte
    int (*Add)(int, int);
}; 
int main(){
    
    //結(jié)構(gòu)體賦值
    struct Student stu = {"張三", 23, 99.5};
    stu.Add = &add;
    int result = stu.Add(1, 2);
    printf("result = %d\n", result);
}

聯(lián)合體

#include <stdio.h> 
#include <stdlib.h>
union Type{
    char *a;
    int b;
    double c;
};
int main(){
    union Type t;
    t.a = "abc";
    t.c = 124.1234;
    
    return 0;
}
  • 聯(lián)合體和結(jié)構(gòu)體區(qū)別
  結(jié)構(gòu)體大小, 是所有數(shù)據(jù)大小之和, 
  聯(lián)合體共享內(nèi)存. 采用最大的那個數(shù)據(jù)類型大小, 聯(lián)合體賦值一次, 賦值多次沒有意 
  義, 因為后面的會覆蓋前面的數(shù)據(jù).

枚舉


enum DAY{
    Mon, Tues, Web, Thur, Fri, Satu, Sun
};

int main(){
    enum DAY today = Sun;
    switch(today){
        case Mon:
            break;
        case Tues:
            break;
        case Web:
            break;
    }
    return 0;
}

typedef(給類型起別名)

typedef int size;
//給別名起別名 
typedef size length;
typedef length width;
typedef length height;

struct Student{
    char *name;
    int age;
}; 

typedef struct Student *Stu;

int main(){
    int a = 123;
    size b = 123;
    width c = 1;
    height d = 2;
    
    Stu s = {"玲玲", 21};
    return 0;
}

宏定義(#define)

#define PI 3.1415926;
//方法模板
define AREA(r) PI * r * r;
int main (){
  double result = AREA(2);
  printf("result = %lf\n", result);
}

c語言語法

一. 字符串格式化輸出

  1. %d 整數(shù) int類型
  2. %s 字符串類型
  3. %f float類型
  4. %.3lf double類型, 保留3位小數(shù)
  5. %p 指針類型
  6. %% 打印一個百分號
  7. %c 字符類型
  8. \0 不可見字符, 字符串結(jié)尾, 存儲結(jié)束
  9. %hd short int 類型
  10. %u unsigned int
  11. %lu unsigned long

二. 隨機數(shù)

  1. arc4random_uniform(n)產(chǎn)生一個0到n-1的隨機數(shù)
  2. 10-20的隨機數(shù), 最大數(shù)-最小數(shù)+1 + 最小數(shù) 如下:
    arc4random_uniform(20-10+1) + 10

三. goto語句

  1. 使用方法: 標簽名: 語句 在需要跳轉(zhuǎn)的地方, goto 標簽名, 容易造成死循環(huán), 如下
  2. 可以向前跳, 也可以向后跳.
  3. 只能在當前函數(shù)中使用
  4. 標簽名下面的第一行代碼, 不能定義變量
int main(int argc, const char * argv[])
{
loop:
    // insert code here...
    printf("Hello, World!33333\n");
    float f = 1.234554654;
    printf("f = %.2lf\n", f);
    int r = random2(10);
    if(r<6)
    {
        goto loop;
    }
    printf("r = %d\n", r);
    
    return 0;
}

四. xcode調(diào)試

  1. 調(diào)試時, 高亮選中的代碼是一個函數(shù), 按下step over, 跳過函數(shù), 執(zhí)行下一步
  2. 如果, 想進入函數(shù), 按下step in

五. 原, 反, 補碼

  1. 正數(shù), 原反補碼, 一樣
  2. 負數(shù), 原反補碼, 不一樣
  3. short int num = 12; 在內(nèi)存中兩個字節(jié)
  4. int num = 1234; 四個字節(jié)
  5. long int num = 213435554; 8個字節(jié) 64位系統(tǒng), 4個字節(jié) 32位系統(tǒng)

六. 垃圾值的由來, 我們聲明一個局部變量, 在內(nèi)存回收的時候, 只是標記不在使用,

而不會清理內(nèi)存中的數(shù)據(jù), 再次分配給其他變量時, 數(shù)據(jù)會分配給新的變量.

七. 數(shù)組初始化方式

  1. 先聲明, 再賦值

    int arr[3];
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;
    
  2. 聲明數(shù)組時, 初始化數(shù)組元素, 也可以省略數(shù)組長度

    int arr[3] = {1, 2, 3};
    int arr[] = {1,, 2, 3};
    
  3. 賦值時, 指定數(shù)組元素個數(shù), 后面大括號中的元素可以不等于數(shù)組長度, 會自動截取, 或者補0

```
int arr[3] = {1, 2, 3, 4, 5};
int arr[3] = {1};
```
  1. 指定下標的初始化

    int arr[3] = {[1]=2, [2]=3, [3]=4}; 
    
  2. 二維數(shù)組, 行數(shù)可以省略, 列數(shù)不能省略.

    int arr[][4] = {1, 5, 3, 4, 6, 3, 8, 0, 8, 9, 12, 45, 23};
    //行數(shù)
    int rows = sizeof(arr) / sizeof(arr[0]);
    //列數(shù)
    int cols = sizeof(arr[0]) / sizeof(arr[0][0]);
    

八. 字符串

  1. 字符串長度的計算 從左向右遍歷, 遇到\0結(jié)束.

  2. 常用函數(shù)

    // 1, puts()函數(shù), 輸出字符串, 自動換行, 只能輸出字符串, 也不能使用占位符
    char name[] = "jack";
    puts(name);
    
    // 2, gets()函數(shù) 作用: 從控制臺接收一個字符串數(shù)據(jù), 與scanf的區(qū)別, 
    // 可以接收空格, 和scanf()函數(shù)一樣, 不安全
    char name[10];
    printf("請輸入你的姓名: ");
    gets(name);
    puts(name);
    
    // 3, #include <string.h>  
    // strlen(str) 字符串長度
    char name[20] = "237748895985";
    long len = strlen(name);
    printf("len = %lu\n", len);
    
    // 4, int strcmp(str1, str2) compare 比較字符串
    //   等于0 相等
    //   大于0 str1大
    //   小于0 str2大
    char name1[12] = "345454";
    char name2[12] = "2345465768";
    int num = strcmp(name1, name2);
    if(num==0){
        
    }
    
    // 5, strcpy(str1, str2)函數(shù) copy, 將str1 拷貝到str2中\(zhòng)0也拷貝
    
    // 6, strcat(str1, str2)函數(shù). concat: 鏈接
    將str2連接到str1上
    
    // 7, fputs(str, stdout); file 將字符數(shù)據(jù)輸出到指定的流中
        標準輸入流和標準輸出流 stdin, stdout
        
    // 8, fopen(path, mode)函數(shù), 可以創(chuàng)建一個指向文件的指針.
        FILE * pFile = fopen("/Users/wwf/a.txt", "a");
        char *name = "黑馬程序員";
        fputs(name, pFile);
        fclose(pFile);
        
    // 9, fclose(file pointer)關(guān)流
    
    // 10, fgets()函數(shù), 從控制臺接收用戶輸入字符串
        scanf()缺點, 不安全, 輸入的空格會被認為結(jié)束
        gets()缺點, 不安全
        fgets(<#char *restrict#>, <#int#>, <#FILE *#>)
        參數(shù)一: 將字符串存到那個數(shù)組中
        參數(shù)二: 接收字符串的長度
        參數(shù)三: 指定流
    // 11, 從文件流中讀取內(nèi)容
        FILE * pFile = fopen("/Users/wwf/a.txt", "r");
        char name[50];
        fgets(name, 50, pFile);
        fclose(pFile);
        printf("name = %s\n", name);
    

九. 指針: 變量的地址 指針在內(nèi)存中占據(jù)8個字節(jié)

  1. 指針變量 存儲指針的變量, 只能用來存儲地址

    int *p1;
    int num = 10;
    p1 = &num;
    // p1的值
    printf("p1 = %p\n", p1);
    // p1的地址
    printf("p1 = %p\n", &p1);
    
  2. *p1 代表指針指向的變量

  3. 批量聲明指針

    int *p1, *p2, *p3;
    // NULL 不指向任何地址, 完全等價于0
    int *p1 = NULL;
    
  4. 野指針 聲明一個指針變量, 未初始化, 是一個垃圾值, 隨機的.
    未初始化, 直接使用.

  5. 多級指針

    1. 二級指針: 指針變量存儲的是, 一級指針的地址,
    2. 三級指針: 指針變量存儲的是, 二級指針的地址.
    3. 一級指針, 只能存儲普通變量的地址
    4. 二級指針, 只能存儲一級指針變量的地址
    5. 三級指針, 只能存儲二級指針變量的地址
    6. n級指針, 只能存儲n-1級指針變量的地址
    int num = 12;
    int *p1 = &num;
    int **p2 = &p1;
    int ***p3 = &p2;
    
  6. 指針的運算

    1. 指針可以和整數(shù)進行加減運算
    2. 指針+1 并不是+1, 而是增加一個單位變量所占用的字節(jié)數(shù)
    3. 指針之間只能做減法運算, 其他運算沒有意義
  7. 指針遍歷數(shù)組的元素

    int arr[] = {3, 6, 3, 9, 23};
    int *p = arr;
    int len = sizeof(arr)/sizeof(arr[0]);
    for(int i = 0; i < len; i++)
    {
        printf("arr[%d] = %d\n", i, *(p++));
    }   
    
  8. 指針與指針之間的減法運算, 結(jié)果是一個long類型的數(shù)據(jù)

    結(jié)果的意義代表兩個指針變量之間相差多少個單位變量

  9. 指針與指針之間,比較運算

    內(nèi)存分配時, 先分配高字節(jié), 再分配低字節(jié).

十. 內(nèi)存中的五大區(qū)域

  1. BSS段
    未初始化的全局變量和靜態(tài)變量, 程序在剛運行的時候,未初始化.

  2. 數(shù)據(jù)段/常量區(qū)
    全局變量初始化為0后, 存到常量區(qū).
    已經(jīng)初始化的全局變量, 靜態(tài)變量和常量等.

  3. 代碼段
    用來存儲程序的代碼/指令

  4. 字符數(shù)組和字符指針的區(qū)別

    // 都是以字符串數(shù)組存儲
    //可以修改值
    char arr[] = "jkklg"; 
    //不可以修改值
    char *arr1 = "dff";
    // 字符串恒定性, 以字符指針形式存儲的字符串.
    
  5. 從文件流中讀取字符串

    FILE * pFile = fopen("/Users/wwf/a.txt", "r");
    char name[50];
    fgets(name, 50, pFile);
    fclose(pFile);
    printf("name = %s\n", name);
    

十一. const關(guān)鍵字 常量

  1. const 修飾數(shù)組

    int arr[4] = {1, 4, 6, 8}; //數(shù)組元素的值不能修改
    
  2. const 修飾指針

    // 無法通過p指針去修改指針指向的變量的值. 直接操作變量可以
    int num = 14;
    const int *p = &num;
    // 可以把另外一個的變量的地址, 賦值給p
    int num2 = 15;
    p = &num2;
    // p的值不能改, 但是可以通過p修改指向的變量的值.
    int * const p = &num;
    *p = 16;
    // 都不能該
    const int * const p = &num;
    

十二. 如何申請堆空間內(nèi)存

  1. 三個函數(shù): malloc(size_t) unsigned long類型, 申請, calloc(size, sizeof(int))申請, realloc()釋放; 申請多少個字節(jié)空間, 在stdlib.h頭文件中

  2. 堆中的空間是, 從低字節(jié)開始分配的,不一定連續(xù), 指的是多次molloc()分配內(nèi)存, 每一次分配的字節(jié)數(shù)是連續(xù)的; 棧中的空間, 從高字節(jié)開始分配, 連續(xù)的.

  3. 判斷是否申請成功,

    int *p = malloc(4);
    if(p)//申請成功 等價于p!=NULL
    {
    
    }
    
  4. calloc函數(shù):

    • 作用: 向堆空間申請指定字節(jié)數(shù)的空間
    • 格式: 參數(shù)1: 多少個單位; 參數(shù)2: 每一個單位的字節(jié)數(shù)
    • calloc(3, sizeof(int))
    • 與malloc相比的優(yōu)勢, 申請內(nèi)存后, 系統(tǒng)會將字節(jié)中的數(shù)據(jù)清零.
  5. realloc函數(shù)

    • 擴容

    • 注意: 指針 幾乎可以操作內(nèi)存上的每一個字節(jié). 但是我們還是建議, 不要亂來,

    • 只操作我們申請的字節(jié)空間, 因為, 有可能出現(xiàn)一些問題.

    • 如果長度不夠, 重新開辟一塊新的內(nèi)存將數(shù)據(jù)復(fù)制到其中, 將以前的內(nèi)存釋放.

    • 長度夠, 還使用以前的內(nèi)存

          int * arr = calloc(10, sizeof(int));
          for(int i = 0; i < 10; i++)
          {
              arr[i] = (i+1)*10;
          }
          realloc(arr, 15);
      
      
  6. 指針作為函數(shù)的返回值, 不能使用局部變量的地址.

  7. 指向函數(shù)的指針聲明

    • 指針函數(shù)的指針, 并不是任意的函數(shù)都可以指向
    • 而是有限定的, 要求指向的函數(shù)的返回值類型和參數(shù)描述必須與指針的描述一樣.
    • 聲明語法:
      1. 返回值類型 (*指針名) ([]參數(shù)列表)
        void ( * pFun1) ();
      2. int (*pFun2) (int num1, int num2);
    void test()
    {
        
    }
    int test2(int a, int b)
    {
    }
    
    int main(int argc, const char * argv[])
    {
        void (*pFunc)() = test;
        pFunc();
        (*pFunc)(); 
        
        int (*pTest2)(int a, int b) = test2;
        pTest2();
    }
    

十三. 結(jié)構(gòu)體

  1. 如何使用結(jié)構(gòu)體來創(chuàng)建新的數(shù)據(jù)類型呢?

    語法格式:
    struct 新類型名稱
    {
    // 在這里面寫上, 你創(chuàng)建的類型是由哪些變量聯(lián)合而成的.
    數(shù)據(jù)類型1 小變量名稱1;
    數(shù)據(jù)類型2 小變量名稱2;
    數(shù)據(jù)類型3 小變量名稱3;
    }

  2. 別名:

    typedef char* String;
    typedef struct 
    {
        char *name;
        int age;
        char *sex;
    } Student;
    Student student;
    

十四. 宏定義

  1. 它是個預(yù)處理指令, 在編譯之前執(zhí)行, 在函數(shù)外, #define MAX = 10;

  2. 作用: 可以為一段c代碼定義一個標識, 如果你要使用這段c代碼, 那么你就使用這個標識.

  3. 語法: #define 宏名 宏值

  4. 原理: 在編譯的時候, 就會執(zhí)行源文件中的預(yù)處理指令.會將c代碼中, 使用宏名的地方替換為宏值.

  5. 將c代碼中的宏名替換為宏值的過程叫做 宏替換/宏代換

  6. 宏值可以是任意的東西, 定義時, 不會檢查語法, 宏替換時, 檢查語法

  7. 如果宏值是一個表達式, 那么宏值并不是表達式的結(jié)果, 而是它本身.

    #define N = 10+10+20;
    int main(int argc, const char *argv[])
    {
        int a = 2*N;
        printf("a = %d\n", a);//50
        return 0;
    }
    
  8. 宏值不可更改

  9. 宏值可以是表達式,

    #define C = a+a;
    int main(int argc, const char *argv[])
    {
        int a = 10;
        int c = C;
        printf("c = %d\n", c);
        return 0;
    }
    
  10. 宏可以定義在函數(shù)外或者函數(shù)內(nèi)
    宏從定義的地方一直到文件結(jié)束都可以用, 取消宏undef 宏名,
    取消后, 后面就無法使用宏了

  11. 使用宏的注意點:

    #define MAX(a, b) a+b;
    // #define 空格 宏名 空格 宏值 
    
  12. static 和 extern

    • 修飾成員變量, 在當前模塊中使用, 使用static, 跨模塊使用extern修飾
    • 函數(shù)默認使用extern修飾,
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容