IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言词法元素 -> 正文阅读

[C++知识库]C语言词法元素

系列文章目录

1、C语言综述1
2、C语言字符集2
3、C语言词法元素3



前言

C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发


1、概述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 翻译3~6阶段为预处理词法元素,7阶段开始为词法元素
  2. 若直至某个给定字符为止的输入流字符序列已被分析为预处理单词,则下一个预处理单词是可构成预处理单词的最长的字符序列比如, x ++ + ++y 是不符合定义的,x++已被分析为预处理单词,后面的字符构成不了预处理单词
#include<bits/stdc++.h>
using namespace std;

int main(int argc,char *argv[]){
    int x = 0, y = 0, c;
    c = x ++ + ++ y;
    cout << x  << endl << y << endl << c;  //输出 1 1 1 
    return 0;
}

2、关键字

关键字说明
auto声明自动变量
break跳出当前循环
case开关语句分支
char声明字符型变量或函数返回值类型
const定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变
continue结束当前循环,开始下一轮循环
default开关语句中的"其它"分支
do循环语句的循环体
double声明双精度浮点型变量或函数返回值类型
else条件语句否定分支(与 if 连用)
enum声明枚举类型
extern声明变量或函数是在其它文件或本文件的其他位置定义
float声明浮点型变量或函数返回值类型
for一种循环语句
goto无条件跳转语句
if条件语句
int声明整型变量或函数
long声明长整型变量或函数返回值类型
register声明寄存器变量
return子程序返回语句(可以带参数,也可不带参数)
short声明短整型变量或函数
signed声明有符号类型变量或函数
sizeof计算数据类型或变量长度(即所占字节数)
static声明静态变量
struct声明结构体类型
switch用于开关语句
typedef用以给数据类型取别名
unsigned声明无符号类型变量或函数
union声明共用体类型
void声明函数无返回值或无参数,声明无类型指针
volatile说明变量在程序执行中可被隐含地改变
while循环语句的循环条件
C99新增关键字
_Bool_Complex_Imaginaryinlinerestrict
C11新增关键字
_Alignas_Alignof_Atomic_Generic_Noreturn
_Static_assert_Thread_local

3、标识符

描述
标识符是由非数字字符(包括下划线和大小写字母)及数字构成的序列,其第一个字符应是非数字字符,不同的标识符取决于有效字符的不同
分类

  1. 结构成员或标记
  2. 联合成员或标记
  3. 枚举成员或标记,枚举成员称枚举常量
  4. 自定义类型名
  5. 标签名
  6. 宏名或宏形参

约束

  1. 组成标识符的字符序列不应与组成关键字的字符序列相同
  2. 标识符最大长度没有具体限制,标准规定,宏名或无外部链接的标识符前31个字符定为有效字符(不忽略大小写),外部链接的标识符前6个字符定为有效字符(可忽略大小写),具体由实现定义,存在有效字符相同、非有效字符不同的两个标识符的行为未定义

3.1、标识符作用域

3.1.1、作用域范围

如果在同一名称空间中存在相同标识符的外部声明,则该外部声明将被隐藏,直到当前作用域终止,然后再次可见,先内部,再外部

#include<bits/stdc++.h>
using namespace std;

int a = 100;
void test(){
    int a = 1;
    cout << a;		//输出1
}
int main()
{
    test();
    return 0;
}

  1. 函数(function)作用域:标签,通过冒号隐式声明(go to语句)
  2. 文件(file)作用域:声明标识符的声明符或类型说明符出现在所有块或参数列表之外,在翻译单元的末尾终止,比如全局变量
  3. 块(block)作用域:声明标识符的声明符或类型说明符出现在块内或函数定义中的参数声明列表内,终止于},比如,函数形参
  4. 函数原型(function prototype)作用域:如果声明标识符的声明符或类型区分符出现在函数原型(不是函数定义的一部分)的参数声明列表中,在函数声明的末尾终止
#include<bits/stdc++.h>
using namespace std;

int test1(int a, int b);        //a、b函数原型作用域
                                //buf1、buf2块作用域
int test1(int buf1, int buf2){  
    return buf1 + buf2;
}
int N = 100, M;              //M, N文件作用域

int main()
{
    label: M = test1(N, M);     //label函数作用域
    if(M < 1000){
        goto label;
    }
    cout << M;              //输出 1000
    return 0;
}

  1. 结构、联合和枚举标记的作用域在声明标记的类型区分符时,标记出现后立即开始
  2. 每个枚举常量的作用域都在其在枚举符列表中定义常量的枚举符后立即开始
  3. 任何其他标识符的作用域都是在其声明程序完成后立即开始
#include<bits/stdc++.h>
using namespace std;

enum test{      //枚举作用域开始
    a = 100,  //枚举常量作用域开始
    b
}num;
int main()
{
    cout << 100 + num;   
    return 0;
}

3.1.2、链接(linkage)

通过链接可在不同作用域或同一作用域,引用同一个对象或函数

  1. 外部链接(external):一组翻译单元中指向同一个对象或函数,只需extern,若文件范围内有可见声明则与其具有相同的链接,若文件范围内没有可见声明则为外部链接
  2. 内部链接(internal):一个翻译单元中指向同一个对象或函数,文件作用域 + static,作用:别的文件不能访问
  3. 无链接(none):指向独一无二的实体,声明为对象或函数以外的任何标识符;声明为函数参数的标识符;没有extern的块内声明的对象标识符
  4. 如果在翻译单元中,同一标识符同时出现在内部和外部链接中,则该行为未定义
  5. 函数标识符和文件作用范围的对象默认外部链接
//test2.cpp
int b = 100;

//test1.cpp
#include<bits/stdc++.h>
using namespace std;
static int b = 1000;
void test_fuc(){
    extern int b;
    cout << b;
}
int main()
{
    test_fuc();
    return 0;
}
//多文件编译$g++ -o test test1.cpp test2.cpp,输出1000,有extern但是文件作用范围内有可见声明,所以extern b的链接是内部链接
//将test1的static int b = 1000;语句删除,再次运行输出100,有extern且文件作用范围内没有可见声明,所以extern b的链接是外部链接
//将test2的int b = 100;语句前加上static,再次编译,编译失败

3.1.3、命名空间

不同类别的标识符具有不同的命名空间

类别消除歧义方法
标签名称通过标签声明和使用的语法消除歧义
结构、联合和枚举的标记通过跟随关键字struct、union或enum来消除歧义
结构或联合的成员通过. 或 ->运算符访问成员时使用的表达式类型消除歧义
所有其他标识符称为普通标识符在普通声明器中声明或作为枚举常量声明
//正常编译
#include<bits/stdc++.h>
using namespace std;
struct test1
{
    int a = 1;
}test1;
int main()
{
    int test1 = 100;
    return 0;
}

3.1.4、生存期

  1. 静态(static)存储期:外部链接、内部链接、存储类说明符static,程序启动前初始化一次,保存存储最后一次修改,程序生存周期
  2. 自动(automatic)存储期:无链接且无static,声明对象的块中、从块外跳转到块中(可能不会初始化),保证保留值;块结束时不再保证保留值

3.2、类型

存储在对象的值或由函数返回的值的意义由访问它的表达式的类型决定

  1. 对象类型(描述对象的类型)
  2. 函数类型(描述函数的类型)
  3. 不完整类型(描述对象的类型,但还缺少决定其尺寸所需信息)

3.2.1、基本类型

在这里插入图片描述

请添加图片描述
说明

结构类型一组按顺序分配的成员对象,每个成员对象都有一个可选的指定名称和可能不同的类型
联合类型一组重叠的成员对象,每个成员对象都有一个可选的指定名称和可能不同的类型
数组类型(T数组)描述相邻接分配的对象的非空集合,具有特定成员对象类型(称为元素类型),从其元素类型派生,以其元素类型和数组成员数为特征,过程称称数组类型的派生
函数类型(返回T的函数)具有指定返回类型的函数,特征是其返回类型及其参数的数量和类型,从其返回类型派生,过程称称函数类型的派生
指针类型(引用类型、(指向)T的指针)描述一类对象,该类对象的值提供对引用类型实体的引用,可以派生自函数类型、对象类型或称为引用类型的不完整类型,过程称指针类型的派生
派生类型构造派生类型的方法可以递归使用
派生声明符类型从T构造派生
无符号整数类型涉及无符号操作数永远不会溢出,详见类型转换
char型应足够大存储基本执行字符集的任何成员,源字符集成员的值保证为正
整型(integral)由纯二进制计数系统定义值
浮点类型表示法未作规定
不完整类型如何变得完整
未知尺寸的数组类型在以后的声明(内部、外部链接)指定尺寸后成为完整类型
未知内容的结构或联合在以后同一作用域声明相同的结构或联合标记以及定义的内容时成为完整类型
void类型永不可能完整的不完整类型

3.2.2、限定类型

以上每一种非限定类型都有三种相应的限定形式。限定形式与非限定形式属同一类型类别,相同表示和对齐要求的不同类型。派生类型不受派生它的类型的限定词限定,比如,const int * 类型是派生自const int的类型

#include<bits/stdc++.h>
using namespace std;
int main()
{
    const int a = 1;
    const int b = 100;		
    const int *c = &a;	
    c = &b;				//c可以修改值,而a、b、*c都不能修改值
    cout << *c; 
    return 0;
}
  1. const(常量)限定
  2. volatile(易变型)限定4
  3. 兼有两种限定

3.2.3、相容类型

类型相同即为相容类型?

  1. 相容结构:成员个数、成员名、成员顺序、位段宽度相同,且成员类型相容
  2. 相容联合:成员个数、成员名、位段宽度相同,且成员类型相容
  3. 相容枚举:成员个数、成员名,且他们的成员具有相同的值

3.2.4、复合类型

从两种相容类型可构造出复合类型?,复合类型是与两种类型均相容的类型且满足以下条件:

  1. 若一种类型是已知尺寸的数组,则复合类型是该尺寸的数组
  2. 若仅有一种类型是带形参表的函数类型(函数原型),则复合类型是带该形参表的函数原型
  3. 若两种类型都是带形参表的函数类型,则复合的形参类型表中的每个形参类型是对应形参的相容类型

3.2.5、类型转换

  1. 显式转换
  2. 隐式转换

整型和整型

  1. 转换后的类型能表示转换前的类型的值,则值不变
  2. 有符号负值转换为无符号值小转大:加上比无符号值最大值大1的值;
  3. 转换成无符号值大转小:除以无符号值最大值大1的值得到的非负余数
  4. 转换成有符号值大转小:实现定义

浮点型和整型

  1. 浮点型转整型,忽略小数部分,若整数部分的值该整型不能表示,未定义
  2. 整型转浮点型,能确切表示则值不变,若不能确切表示,实现定义为接近、稍小、稍大的值

浮点型和浮点型

  1. 升格值不变
  2. 降格,若值表示不了则未定义,若不能确切表示则实现定义为接近、稍小、稍大的值

一般算术转换
运算过程中的隐式转换,比如,整数类型加上浮点类型,会先将整数类型转换成浮点类型。总是小的转换成大的,,unsigned int可能比long int范围大,转换成unsigned long int

4、常量

每个常量都有一个类型,由其形式和值决定,常数的值应在其类型的代表值范围内。

4.1、浮点常量

最终值若在类型可表示的值范围内且不能确切表示,结果或是最接近的可表示的值,或是比最接近的可表示的值稍小,或是比最接近的可表示的值稍大,由实现定义
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;

int main(int argc,char *argv[]){

    //测试typeid().name()函数,输出变量类型
    float test1 = 1.1;
    double test2 = 1.1;
    int test3 = 1;
    long double test4 = 2;
    cout << typeid(1).name() << endl;				//输出 i
    cout << typeid(test1).name() << endl;		//输出 f
    cout << typeid(test2).name() << endl;		//输出 d
    cout << typeid(test3).name() << endl;		//输出 i
    cout << typeid(test4).name() << endl << endl;		//输出 e
    //小数部分常量 + 指数部分 + 浮点后缀符
    cout << 1. << endl;  					//输出 1
    cout << typeid(1.).name() << endl;					//输出 d
    cout << .11 << endl;					//输出 0.11
    cout << typeid(.11).name() << endl;					//输出 d
    cout << 1.1 << endl;					//输出 1.1
    cout << typeid(1.1).name() << endl;					//输出 d
    
    cout << 1.e-1F << endl;  					//输出 0.1
    cout << typeid(1.e-1F).name() << endl;					//输出 f
    cout << .1e+1f << endl;  					//输出 1
    cout << typeid(.1e+1f).name() << endl;					//输出 f
    
    //数字字符序列 + 指数部分 + 浮点后缀符
    cout << 0e0 << endl;  					//输出 0
    cout << typeid(0e0).name() << endl;					//输出 d
    cout << 00221e-1l << endl;  					//输出 22.1
    cout << typeid(00221e-1l).name() << endl;					//输出 e
    cout << 0511e+22L << endl;  					//输出 5.11e+24
    cout << typeid(0511e+22L).name() << endl;					//输出 e
    return 0;
}

4.2、整数常量

在这里插入图片描述
递归了属于是
请添加图片描述

# include <bits/stdc++.h>
using namespace std;
int main()
{
    printf("%d %s\n", 11,typeid(11).name());			//输出 11 i
    printf("%d %s\n", 011,typeid(011).name());			//输出 9 i
    printf("%d %s\n", 0x11,typeid(0x11).name());			//输出 17 i

    printf("%lu %s\n", 011ul,typeid(011ul).name());			//输出 9 m
    printf("%u %s\n", 11u,typeid(11u).name());			//输出 11 j
    printf("%ld %s\n", 11l,typeid(11l).name());			//输出 11 l
    return 0;
}

4.3、枚举常量

枚举常量即其标识符,标识符的类型为int

4.4、字符常量

单引号内一个或多个字符

在这里插入图片描述
约束
八进制或十六进制转义序列的值对于整型字符常量应在unsigned char类型的表示范围内,而对宽字符常量则应在wchar_t的无符号类型表示范围内

# include <bits/stdc++.h>
using namespace std;
int main()
{
    
    cout << '\0' << ' '<< typeid('\0').name() << endl;		//输出 c
    cout << '\102'<<' '<< typeid('\102').name() << endl;		//输出B c 
    cout << '\x66'  << ' '<< typeid('\x66').name() << endl;		//输出f c
    cout << '\\' << ' '<< typeid('\\').name() << endl;		//输出\ c

    cout << L'\0' << ' '<< typeid(L'\0').name() << endl;		//输出0 w
    cout << L'\102'<<' '<< typeid(L'\102').name() << endl;		//输出66 w
    cout << L'\x66'  << ' '<< typeid(L'\x66').name() << endl;		//输出102 w
    cout << L'\\' << ' '<< typeid(L'\\').name() << endl;		//输出92 w
    return 0;
}

cout << 'ab' << ' '<< typeid('ab').name() << endl; //输出 24930 i
/*
test.cpp:16:13: warning: multi-character character constant [-Wmultichar]
     cout << 'ab' << ' '<< typeid('ab').name() << endl;
             ^~~~
test.cpp:16:34: warning: multi-character character constant [-Wmultichar]
     cout << 'ab' << ' '<< typeid('ab').name() << endl;
                                    ^~~~
*/
cout << L'ab' << ' '<< typeid(L'ab').name() << endl; //输出 98 w
/*
test.cpp:16:13: warning: character constant too long for its type
     cout << L'ab' << ' '<< typeid(L'ab').name() << endl;
             ^~~~~
test.cpp:16:35: warning: character constant too long for its type
     cout << L'ab' << ' '<< typeid(L'ab').name() << endl;
                                   ^~~~~
*/
cout << L'寄' << ' '<< typeid(L'寄').name() << endl;   //无警告,输出 23492 w

//cout << '' ; 报错

4.5、字符串常量

相邻的字符串常量会被连接成单个字符串并在最后添加一个空字符,宽字符串同理,但是相邻的宽字符串和字符串相邻行为未定义,比如,cout << "\102"“666”;

在这里插入图片描述

# include <bits/stdc++.h>
using namespace std;
int main()
{
    cout << "\0444" << ' '<< typeid("\0444").name() << endl;		//输出$4 A3_c
    cout << "\1026666"<<' '<< typeid("\1026666").name() << endl;	//输出B6666 A6_c
    cout << "\x66ssss"  << ' '<< typeid("\x66ssss").name() << endl; //输出fssss A6_c
    cout << L"\\adsad" << ' '<< typeid(L"\\adsad").name() << endl;	//输出0x4040b4 A7_w
    cout << L"" << ' '<< typeid(L"").name() << endl;	//输出0x4040c2 A1_w
    cout << "" << ' '<< typeid("").name() << endl;	//输出 A1_c
    cout << "\102""44" << ' '<< typeid("\102""44").name() << endl; 	//输出B44 A4_c
    return 0;
}

5、算符

内容
[ ] ( ) . ->
++ – & * + - ~ ! sizeof
/ % << >> < > <= >= == != ^ | && || ? :
= *= /= %= += -= <<= >>= &= ^= |= , # ##

优先级5

约束
[]、()、?:应成对出现,#和##只出现在宏定义和预处理指令中

6、标点符号

内容
[ ] ( ) { } * , : = ; … #

约束
[ ] ( ) { }成对出现,#只出现在预处理指令中

7、头文件名

在这里插入图片描述

# include <<bits/stdc++.h>		//报错
# include <bits/stdc>			//报错
# include <bits/stdc++.h>>		//未报错,没有被判定为头文件,h-字符可以用<而不能用>
# include "bits/stdc"			//报错

约束
只能出现在#include 预处理指令中, ’ " \ or /* 出现在<>中未定义,’ \ or /* 出现在""中未定义

8、预处理数(pp-number)

内容
以数字开头,前面可选地加上句点(.),后面可以是字母、下划线、数字、小数点和e+、e-、E+或E-字符序列,覆盖浮点数和整数

9、注释(Comments)

内容
由/*引出注释,除非/*在字符常量、字符串常量、注释中。检查注释内容的过程包括识别多字节字符和找到 */序列

/*adsad/*sdasdas/*sdasd*/     //正常
/*adsad/*sdasdas/*sda*/sd*/     //错误
/*adsad/*sdasdas/*sdasd/*/**/     //错误

10、其他

10.1、左值

  1. 左值是指示对象的表达式,是一种对象类型或除void外的不完整类型,当一个对象被称为具有特定类型时,该类型由用于指定该对象的左值指定。
  2. 可修改左值,不具有数组类型、不具有不完整类型、不具有常量限定类型,并且如果它是结构或联合,则不具有任何具有常量限定类型的成员(递归地包括所有包含的结构或联合的任何成员)。
  3. 除sizeof的操作数、一元&运算符、++运算符、–运算符、算符或赋值运算符的左操作数,不具有数组类型的左值将转换为存储在指定对象中的值(不再是左值)。如果左值具有限定类型,则该值具有左值类型的非限定版本;否则,该值具有左值的类型。如果左值的类型不完整且没有数组类型,则行为未定义。
  4. 除sizeof运算符的操作、一元&运算符的操作数、用于初始化字符类型数组的字符串常量、用于初始化与wchar_t兼容的元素类型数组的宽字符串常量,将具有x type的数组的左值 转换为指向x type的指针 的表达式,且其指向数组对象的初始成员,并且不是左值。
  5. 自我理解:左值即对象的定位符值,作为一个定位的作用,右值即作为一个值的作用
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int a = 0, b = 0;
    a = b++;    //a是左值,b既为左值也为右值
    b = a;      //b是左值,a是右值
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int a[10] = {1, 2, 3};
    sizeof(a); cout << &a; //a是左值
    int *b = a; //a不是左值,指向对象的初始成员,b是左值,定位到一个指针型变量
    return 0;
}

10.2、函数指示符

函数指示符是具有函数类型的表达式。除非是sizeof运算符或一元运算符&的操作数,否则类型为“返回type类型的函数 ”的函数指示符将转换为类型为“指向返回type类型的函数的指针 ”的表达式

#include <bits/stdc++.h>
using namespace std;
int test(){
    cout << 100;
    return 100;
}
int main()
{
    int(*a)();
    a = *test;
    a();		//输出100
    return 0;
}

10.3、void

void表达式(类型为void的表达式),其实际不存在值不得以任何方式使用,且不得将此类表达式隐式或显式转换为其他类型。如果任何其他类型的表达式出现在需要void表达式的上下文中,则此其他类型的表达式的值或指示符将被忽略。对void表达式求值仅是为了获得副作用,或使用void *。

10.4、指针

  1. 指向void的指针可以转换为指向任何不完整或对象类型的指针,反之亦然
  2. 指向任何不完整或对象类型的指针转换为指向void的指针并再次返回,结果与原始指针相同
  3. 指向非限定类型的指针可以转换为指向该类型的限定版本的指针,且原始指针和转换指针的值应相等
  4. 值为0的整型常量表达式、转换为void*类型的此类表达式称为空指针常量,保证不等于任何对象和函数的指针
#include <bits/stdc++.h>
using namespace std;
int main()
{
    void* c;
    int b = 100;
    int* a = &b;
    c = a;                              //void指针转对象类型指针
    cout << *(int *)(void *)a << endl;  //对象类型指针转void指针并再次返回
    cout << a << endl;                  //非限定类型指针
    cout << (const int *)a;             //转限定类型指针
    a = 0;                              //空指针
    return 0;
}	
/*	
输出				
100
0x61fe0c
0x61fe0c
*/

?
?
?
?
?
?
?
?


以上纯属个人观点,欢迎大佬批评指正
  1. https://blog.csdn.net/init33/article/details/121258745 ??

  2. https://blog.csdn.net/init33/article/details/121318734 ??

  3. https://blog.csdn.net/init33/article/details/121319873 ??

  4. https://blog.csdn.net/weixin_38815998/article/details/102840096?ivk_sa=1024320u ??

  5. https://baike.baidu.com/item/%E8%BF%90%E7%AE%97%E7%AC%A6%E4%BC%98%E5%85%88%E7%BA%A7/4752611?fr=aladdin ??

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-15 15:39:53  更:2021-11-15 15:42:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 0:01:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码