C语言笔记归纳2:数据类型与变量

C语言数据类型与变量详解

数据类型与变量

目录

数据类型与变量

一、数据类型:C 语言的 “数据容器”(选对容器才不浪费空间)

1. 数据类型分类(一张表分清)

2. 内置类型详解(避坑 + 实用场景)

(1)字符型:最小的 “迷你容器”(占 1 字节)

(2)整型:整数的 “专属容器”(按大小分 4 类)

(3)浮点型:小数的 “精度容器”(按精度分 3 类)

(4)布尔型:真 / 假的 “迷你容器”(C99 新增)

3. 类型选择原则(新手不纠结)

二、sizeof 操作符:测量 “容器” 的大小(避免装不下数据)

1. sizeof 的 3 种用法(简单到不用记)

2. 内存单位换算(通俗解释)

3. 常见类型大小(32 位 / 64 位系统通用)

4. 核心陷阱:sizeof 不执行表达式!

5. 输出格式:用 % zd(跨平台兼容)

三、signed 与 unsigned:控制 “正负号” 的开关

1. 核心区别(一张表看懂)

2. 实用示例(含溢出陷阱)

3. 适用场景

四、数据类型的取值范围:别让数据 “装不下”

1. 整型取值范围:查 limits.h 头文件

2. 浮点型取值范围:查 float.h 头文件

3. 溢出的危害(新手必看)

五、变量:“容器” 的具体实例(给容器起名字)

1. 变量的创建与初始化(避免垃圾数据)

2. 变量命名规则(别踩命名坑)

3. 全局变量 vs 局部变量(核心区别)

4. 同名变量:局部覆盖全局

六、算术操作符:数据的 “运算工具”(加减乘除取余)

1. +(加)、-(减):简单无坑

2. *(乘):别写 × 符号

3. /(除):整数除法是坑王!

核心规则(记牢!):

示例(含实际应用):

4. %(取模 / 取余):仅支持整数

核心规则:

示例:

七、赋值操作符:给 “容器” 装东西(别和等于号搞混)

1. =(简单赋值):从右向左装

2. 复合赋值:简化操作(高效不易错)

八、单目操作符:只需一个 “容器” 的操作(自增自减是重点)

1. ++(自增)、--(自减):容器自身 ±1

核心口诀(记死!):

前置++示例:

后置++示例:

避坑:别在一个表达式里多次用++/--

2. +(正号)、-(负号):简单无坑

九、强制类型转换:强制换 “容器”(慎用!)

1. 示例(含风险):

2. 避坑:括号别漏!

十、scanf 与 printf:数据的 “输入输出门窗”(新手最易踩坑)

1. printf:格式化输出(按规矩展示)

核心语法:

实用技巧(格式化输出更美观):

2. scanf:格式化输入(按规矩接收)

核心语法:

常用占位符(与 printf 对应):

高频避坑(新手必看!):

坑 1:% c 读取空白字符

坑 2:% s 读取含空格的字符串

坑 3:赋值忽略符*(跳过不需要的输入)

坑 4:用返回值判断输入是否有效

场景:多组输入(比如计算多组 a+b),输入到 Ctrl+Z 结束;


✨ 引言:

为什么这部分知识点是 C 语言的 “核心骨架”?

学 C 语言就像盖房子 —— 数据类型是 “砖瓦”(存储数据的容器),操作符是 “工具”(处理数据的手段),输入输出是 “门窗”(与外界交互的通道)。这三部分直接决定你能否写出 “能跑、没错、好用” 的代码,也是新手最容易踩坑的地方!

一、数据类型:C 语言的 “数据容器”(选对容器才不浪费空间)

数据类型就像不同规格的 “收纳盒”—— 装整数用 “整型盒”,装小数用 “浮点盒”,装单个字符用 “字符盒”,盒子的大小(长度)决定了能装多少东西(取值范围)。

1. 数据类型分类(一张表分清)

类型大类具体类型核心用途新手优先级
内置类型(自带)字符型(char、signed char 等)存单个字符(如 'a')、小范围整数⭐⭐⭐⭐⭐
整型(int、long、long long)存整数(如年龄、分数、数量)⭐⭐⭐⭐⭐
浮点型(float、double)存小数(如身高、体重、金额)⭐⭐⭐⭐⭐
布尔型(_Bool、bool)存 “真 / 假”(如判断条件)⭐⭐⭐⭐
自定义类型(后续学)数组、结构体、枚举等存复杂数据(如学生信息、商品列表)⭐⭐⭐

2. 内置类型详解(避坑 + 实用场景)

(1)字符型:最小的 “迷你容器”(占 1 字节)
类型取值范围实用场景注意事项
char-128~127存字符(如'a''5'默认带符号(signed char)
signed char-128~127需存负的小整数(如 - 10)明确声明带符号
unsigned char0~255仅存非负小整数(如 200)最大值是 signed char 的 2 倍

💡 小技巧:字符型本质是 “1 字节整数”,存字符时实际存的是 ASCII 码(比如'a'=97),所以能做算术运算(如'a' + 32 = 'A')。

(2)整型:整数的 “专属容器”(按大小分 4 类)

新手记住 “优先用 int,超范围用 long long” 就够了!

类型内存长度(32 位 / 64 位)取值范围日常场景
short2 字节(固定)-32768~32767存小整数(如年龄 18)
int4 字节(固定)-21 亿~21 亿首选(分数、数量等)
long4 字节 / 8 字节随系统跨平台兼容时用
long long8 字节(固定)-9e18~9e18存超大整数(如人口数)
无符号版本同对应有符号类型0~ 最大值(翻倍)仅存非负(如索引、金额)
(3)浮点型:小数的 “精度容器”(按精度分 3 类)
类型精度(有效数字)内存长度新手选择避坑点
float6~7 位4 字节内存紧张时用(如嵌入式)赋值必须加f3.14f
double15~17 位8 字节首选(精度高、兼容性好)默认小数类型(3.14是 double)
long double18~19 位8/10 字节科学计算(如航天数据)不同编译器支持差异大
(4)布尔型:真 / 假的 “迷你容器”(C99 新增)

专门用来表示 “是 / 否”,需包含头文件#include <stdbool.h>

#include <stdio.h>
#include <stdbool.h> // 必须加这个头文件
int main()
{
    bool is_ok = true;  // true=1(真)
    _Bool is_error = false; // false=0(假)
    
    if (is_ok) {
        printf("执行成功\n"); // 会执行
    }
    if (5) { // C语言规则:非0即真(-1、3.14都算真)
        printf("非0为真\n"); // 会执行
    }
    return 0;
}

3. 类型选择原则(新手不纠结)

  • 整数:先试int,不够用就换long long
  • 小数:直接用double,别用float(精度不够易出错);
  • 字符:用char,存非负小整数用unsigned char
  • 真假:用bool(记得加头文件)。

二、sizeof 操作符:测量 “容器” 的大小(避免装不下数据)

每种容器(数据类型)的大小不同,用sizeof能精确测量,单位是字节(Byte) —— 这直接决定了数据能不能装下(比如用short存 200000 会溢出)。

1. sizeof 的 3 种用法(简单到不用记)

#include <stdio.h>
int main()
{
    int a = 10;
    // 用法1:测变量
    printf("变量a的大小:%zd\n", sizeof(a));  // 4字节
    // 用法2:测变量(省略括号)
    printf("变量a的大小:%zd\n", sizeof a);   // 4字节(等价于用法1)
    // 用法3:测类型(必须加括号)
    printf("int类型的大小:%zd\n", sizeof(int)); // 4字节
    return 0;
}

2. 内存单位换算(通俗解释)

  • 比特位(bit):最小单位,只能存 0 或 1(比如 “开关”);
  • 字节(Byte):基本单位,1Byte = 8bit(能存 1 个字符,比如'a');
  • 常用单位:1KB=1024Byte(约 1000 个字符)、1MB=1024KB(约 100 万个字符)。

3. 常见类型大小(32 位 / 64 位系统通用)

#include <stdio.h>
#include <stdbool.h>
int main()
{
    printf("bool:%zd字节\n", sizeof(bool));        // 1
    printf("char:%zd字节\n", sizeof(char));        // 1(固定)
    printf("short:%zd字节\n", sizeof(short));      // 2(固定)
    printf("int:%zd字节\n", sizeof(int));          // 4(固定)
    printf("long:%zd字节\n", sizeof(long));        // 4(32位)/8(64位)
    printf("long long:%zd字节\n", sizeof(long long));// 8(固定)
    printf("float:%zd字节\n", sizeof(float));      // 4(固定)
    printf("double:%zd字节\n", sizeof(double));    // 8(固定)
    return 0;
}

4. 核心陷阱:sizeof 不执行表达式!

这是新手最容易踩的坑 ——sizeof里的表达式只是 “摆样子”,不会真的计算:

#include <stdio.h>
int main()
{
    int a = 10;
    short s = 4;
    // 关键点:s = a+5 不会执行,只测s的类型(short=2字节)
    printf("sizeof结果:%zd\n", sizeof(s = a + 5)); // 输出2
    printf("s的实际值:%d\n", s); // 输出4(s没被修改!)
    return 0;
}

5. 输出格式:用 % zd(跨平台兼容)

sizeof的返回值是 “无符号整数”(类型名size_t),打印时用%zd最稳妥,避免用%d(某些编译器会报错)。

三、signed 与 unsigned:控制 “正负号” 的开关

signedunsigned是 “类型开关”,只对整型(含 char)有效,控制容器是否能装负数。

1. 核心区别(一张表看懂)

开关含义取值范围特点打印占位符
signed带符号(默认)能存正数、负数、0(如 - 10、20)%d(int)
unsigned无符号只能存 0 和正数(如 0、20)%u(int)

2. 实用示例(含溢出陷阱)

#include <stdio.h>
int main()
{
    signed int a = -20;    // 等价于int a=-20(默认带符号)
    unsigned int b = 20;   // 无符号,不能存负数
    
    printf("signed int:%d\n", a);  // 输出-20(正常显示负数)
    printf("unsigned int:%u\n", b); // 输出20(正常显示)
    
    // 陷阱:给unsigned变量赋负数,会溢出(结果是超大正数)
    unsigned int c = -1;
    printf("unsigned存负数:%u\n", c); // 输出4294967295(32位系统)
    return 0;
}

3. 适用场景

  • unsigned的唯一好处:相同长度下,最大值翻倍(比如unsigned int最大是 4294967295,是signed int的 2 倍);
  • 什么时候用?存非负数据(如年龄、索引、金额),避免负数干扰(比如年龄不可能是 - 5)。

四、数据类型的取值范围:别让数据 “装不下”

每个容器都有 “容量上限”,超出就会 “溢出”(数据错乱),比如用short存 32768(超出最大值 32767),结果会变成 - 32768。

1. 整型取值范围:查 limits.h 头文件

C 语言提供了现成的 “容量表”,包含在limits.h里,不用死记硬背:

#include <stdio.h>
#include <limits.h> // 必须包含
int main()
{
    printf("int最小值:%d\n", INT_MIN);    // -2147483648
    printf("int最大值:%d\n", INT_MAX);    // 2147483647
    printf("unsigned int最大值:%u\n", UINT_MAX); // 4294967295
    printf("long long最大值:%lld\n", LLONG_MAX); // 9223372036854775807
    return 0;
}

2. 浮点型取值范围:查 float.h 头文件

浮点型的 “容量表” 在float.h里,日常用得少,需要时查阅:

#include <stdio.h>
#include <float.h> // 必须包含
int main()
{
    printf("float最大值:%f\n", FLT_MAX);  // 约3.4e38
    printf("double最大值:%lf\n", DBL_MAX); // 约1.8e308
    return 0;
}

3. 溢出的危害(新手必看)

溢出是 “隐形 bug”,编译时不报错,运行时结果错乱:

#include <stdio.h>
#include <limits.h>
int main()
{
    int a = INT_MAX; // a=2147483647(int最大值)
    a = a + 1; // 溢出!超出容量
    printf("a+1的结果:%d\n", a); // 输出-2147483648(数据错乱)
    return 0;
}

五、变量:“容器” 的具体实例(给容器起名字)

变量是 “数据类型的具体容器”—— 比如int age = 18;int是 “容器类型”,age是 “容器名字”,18是 “容器里的东西”。

1. 变量的创建与初始化(避免垃圾数据)

#include <stdio.h>
// 全局变量:定义在main函数外,未初始化默认0
int global_var; 

int main()
{
    // 局部变量:定义在main函数内,必须初始化(否则是随机垃圾数据)
    int local_var = 0; // 推荐:创建时赋值(初始化)
    
    int bad_var; // 不推荐:未初始化,值是随机的
    // printf("%d\n", bad_var); // 报错(VS编译不通过)
    
    printf("全局变量:%d\n", global_var); // 输出0(默认初始化)
    printf("局部变量:%d\n", local_var); // 输出0(手动初始化)
    return 0;
}

2. 变量命名规则(别踩命名坑)

  • 允许用:字母、数字、下划线(_);
  • 禁止用:数字开头(如123var)、关键字(如int int)、中文 / 特殊字符(如变量1);
  • 区分大小写:ageAge是两个不同变量;
  • 推荐风格:用下划线分隔(如student_name),别用驼峰(studentName,C 语言不推荐)。

3. 全局变量 vs 局部变量(核心区别)

特性全局变量(main 外)局部变量(main 内 / 代码块内)
作用域整个程序(所有文件)仅定义的代码块内(出块失效)
生命周期程序运行全程代码块执行时创建,执行完销毁
未初始化值默认 0随机垃圾数据
内存区域静态区栈区

4. 同名变量:局部覆盖全局

如果全局和局部变量同名,优先用局部的(“就近原则”):

#include <stdio.h>
int a = 100; // 全局变量a

int main()
{
    int a = 10; // 局部变量a(与全局同名)
    printf("%d\n", a); // 输出10(局部优先)
    {
        int a = 5; // 代码块内的局部变量a
        printf("%d\n", a); // 输出5(更就近)
    }
    printf("%d\n", a); // 输出10(回到main的局部变量)
    return 0;
}

六、算术操作符:数据的 “运算工具”(加减乘除取余)

算术操作符是处理数据的 “扳手、螺丝刀”,核心有+-*/%,重点避坑整数除法和取模!

1. +(加)、-(减):简单无坑

和数学里的加减完全一致,支持整数、浮点数:

#include <stdio.h>
int main()
{
    int m = 3 + 5; // 8
    float f = 3.5 - 1.2; // 2.3
    printf("%d %f\n", m, f);
    return 0;
}

2. *(乘):别写 × 符号

C 语言里没有×,用*表示乘法:

#include <stdio.h>
int main()
{
    printf("%d\n", 5 * 5); // 25(5×5)
    printf("%f\n", 3.14 * 2); // 6.280000
    return 0;
}

3. /(除):整数除法是坑王!

核心规则(记牢!):
  • 两个操作数都是整数 → 整数除法(只取商,丢弃小数,不是四舍五入);
  • 至少一个是浮点数 → 浮点除法(得到小数)。
示例(含实际应用):
#include <stdio.h>
int main()
{
    printf("6/4(整数除):%d\n", 6 / 4); // 1(丢弃0.5)
    printf("6/4.0(浮点除):%f\n", 6 / 4.0); // 1.500000
    
    // 实际场景:计算5分对应的百分比(满分20)
    int score = 5;
    // 错误:score/20是整数除(0),结果0
    // int percent = (score / 20) * 100;
    // 正确:score/20.0是浮点除(0.25),结果25
    int percent = (score / 20.0) * 100;
    printf("百分比:%d%%\n", percent); // 25%(%%打印%)
    return 0;
}

4. %(取模 / 取余):仅支持整数

核心规则:
  • 作用:求两个整数整除后的余数;
  • 限制:操作数必须是整数(不能是浮点数);
  • 正负号:结果的正负由 “第一个操作数” 决定。
示例:
#include <stdio.h>
int main()
{
    printf("6%%4:%d\n", 6 % 4);  // 2(6÷4商1余2)
    printf("11%%5:%d\n", 11 % 5); // 1
    printf("-11%%5:%d\n", -11 % 5); // -1(第一个数负)
    printf("11%%-5:%d\n", 11 % -5); // 1(第一个数正)
    // printf("6%%4.0:%d\n", 6 % 4.0); // 错误:取模只能是整数
    return 0;
}

七、赋值操作符:给 “容器” 装东西(别和等于号搞混)

赋值操作符是 “装东西的动作”,核心有=(简单赋值)和+=/-=等(复合赋值),重点:=不是 “等于”,是 “赋值”!

1. =(简单赋值):从右向左装

#include <stdio.h>
int main()
{
    int a = 10; // 初始化:创建容器a,装10
    a = 20;     // 赋值:把20装进a(覆盖原来的10)
    printf("%d\n", a); // 输出20
    
    // 连续赋值(不推荐,可读性差)
    int b, c;
    c = b = a + 3; // 先算b = 23,再算c = 23
    printf("%d %d\n", b, c); // 23 23
    
    // 推荐:拆开写
    b = a + 3;
    c = b;
    return 0;
}

2. 复合赋值:简化操作(高效不易错)

a += 3 等价于 a = a + 3,其他同理,代码更简洁:

#include <stdio.h>
int main()
{
    int a = 5;
    a += 3; // a = a+3 → 8
    printf("%d\n", a);
    a -= 2; // a = a-2 → 6
    printf("%d\n", a);
    a *= 4; // a = a*4 → 24
    printf("%d\n", a);
    a /= 3; // a = a/3 → 8
    printf("%d\n", a);
    a %= 5; // a = a%5 → 3
    printf("%d\n", a);
    return 0;
}

八、单目操作符:只需一个 “容器” 的操作(自增自减是重点)

单目操作符只需一个操作数(比如 “给 a 加 1”),核心是++(自增)、--(自减),新手最容易搞混前置和后置!

1. ++(自增)、--(自减):容器自身 ±1

核心口诀(记死!):
  • 前置++/--:先变后用(先改值,再用改后的值);
  • 后置++/--:先用后变(先用原值,再改值)。
前置++示例:
#include <stdio.h>
int main()
{
    int a = 10;
    int b = ++a; // 先a+1=11,再把11赋给b
    printf("a=%d, b=%d\n", a, b); // a=11, b=11
    return 0;
}
后置++示例:
#include <stdio.h>
int main()
{
    int a = 10;
    int b = a++; // 先把10赋给b,再a+1=11
    printf("a=%d, b=%d\n", a, b); // a=11, b=10
    return 0;
}
避坑:别在一个表达式里多次用++/--

比如a++ + ++a,结果未定义(不同编译器答案不同),尽量单独一行用(如a++;)。

2. +(正号)、-(负号):简单无坑

  • +:无意义(默认正数),可省略;
  • -:改变正负号(如-a是 a 的负数);
#include <stdio.h>
int main()
{
    int a = 10;
    int b = -a; // -10
    int c = -(-a); // 10(双重负号抵消)
    printf("%d %d\n", b, c); // -10 10
    return 0;
}

九、强制类型转换:强制换 “容器”(慎用!)

强制类型转换是 “把一个容器里的东西,硬塞进另一个容器”,语法(目标类型) 表达式,可能会 “挤坏东西”(损失精度)。

1. 示例(含风险):

#include <stdio.h>
int main()
{
    // 浮点数转整数:丢弃小数(不是四舍五入)
    int a = (int)3.14; // 3
    int b = (int)5.9;  // 5(不是6!)
    
    // 整数转浮点数:安全(无精度损失)
    float c = (float)10; // 10.000000
    
    // 大范围转小范围:溢出(数据错乱)
    short d = (short)32768; // short最大32767,溢出后是-32768
    printf("%d %d %f %d\n", a, b, c, d);
    return 0;
}

2. 避坑:括号别漏!

(double)3/2 和 (double)(3/2) 完全不同:

#include <stdio.h>
int main()
{
    // 3先转double(3.0),再除以2 → 1.5
    printf("%lf\n", (double)3/2);   // 1.500000
    // 3/2先整数除(1),再转double → 1.0
    printf("%lf\n", (double)(3/2)); // 1.000000
    return 0;
}

十、scanf 与 printf:数据的 “输入输出门窗”(新手最易踩坑)

printf是 “从容器里拿东西给别人看”(输出),scanf是 “从别人那拿东西装进容器”(输入),核心是 “占位符” 要和数据类型匹配!

1. printf:格式化输出(按规矩展示)

核心语法:

printf("格式字符串", 输出项1, 输出项2, ...);

  • 格式字符串:含 “普通字符”(直接显示)和 “占位符”(替换成输出项);
  • 常用占位符(记牢 80% 场景够用):
占位符作用示例代码输出结果
%d打印有符号整数printf("%d", 100);100
%u打印无符号整数printf("%u", 100);100
%c打印单个字符printf("%c", 'a');a
%s打印字符串printf("%s", "张三");张三
%f打印 float 浮点数printf("%f", 3.14f);3.140000
%lf打印 double 浮点数printf("%lf", 3.14);3.140000
%.2f保留 2 位小数(四舍五入)printf("%.2f", 3.1415);3.14
%zd打印 sizeof 返回值printf("%zd", sizeof(int));4
实用技巧(格式化输出更美观):
#include <stdio.h>
int main()
{
    // 1. 限定宽度(右对齐,不足补空格)
    printf("%5d\n", 123); //  123(前面补2空格)
    // 2. 左对齐
    printf("%-5dhehe\n", 123); // 123  hehe(后面补2空格)
    // 3. 显示正负号
    printf("%+d\n", 10); // +10
    printf("%+d\n", -10); // -10
    // 4. 输出部分字符串(前3个字符)
    printf("%.3s\n", "hello world"); // hel
    return 0;
}

2. scanf:格式化输入(按规矩接收)

核心语法:

scanf("格式字符串", &变量1, &变量2, ...);

  • 关键坑:变量前必须加&(取地址符),告诉 scanf “东西装到哪”;
  • 数组例外:数组名本身是地址,不用加&
  • VS 使用前置:文件第一行加#define _CRT_SECURE_NO_WARNINGS 1(屏蔽安全警告)。
常用占位符(与 printf 对应):
占位符作用代码示例
%d读取有符号整数scanf("%d", &a);
%u读取无符号整数scanf("%u", &b);
%c读取单个字符scanf(" %c", &ch);
%s读取字符串(遇空白停止)scanf("%10s", arr);
%f读取 float 浮点数scanf("%f", &f);
%lf读取 double 浮点数scanf("%lf", &d);
高频避坑(新手必看!):
坑 1:% c 读取空白字符

问题:scanf("%c")会读入前一个输入的换行 / 空格,导致读不到想要的字符;解决方案:在%c前加空格(scanf(" %c", &ch));

#include <stdio.h>
int main()
{
    int a;
    char ch;
    scanf("%d", &a); // 输入10后按回车(缓冲区残留换行)
    // scanf("%c", &ch); // 读入换行,输出空
    scanf(" %c", &ch); // 忽略空白,正确读入
    printf("a=%d, ch=%c\n", a, ch);
    return 0;
}
坑 2:% s 读取含空格的字符串

问题:输入 “hello world”,scanf("%s", arr)只读到 “hello”;解决方案:用%[^\n]读取到换行前的所有字符,同时指定长度避免溢出;

#include <stdio.h>
int main()
{
    char name[20];
    // 读取含空格的字符串,最多19个字符(留1个存\0)
    scanf("%19[^\n]", name);
    printf("你输入的是:%s\n", name); // 输入"张三 18",输出完整内容
    return 0;
}
坑 3:赋值忽略符*(跳过不需要的输入)

场景:读取日期 “2025-11-15”,跳过 “-”;

#include <stdio.h>
int main()
{
    int year, month, day;
    // %*c跳过一个字符(这里是'-')
    scanf("%d%*c%d%*c%d", &year, &month, &day);
    printf("%d年%d月%d日\n", year, month, day); // 输入2025-11-15,输出正确
    return 0;
}
坑 4:用返回值判断输入是否有效
场景:多组输入(比如计算多组 a+b),输入到 Ctrl+Z 结束;
#include <stdio.h>
int main()
{
    int a, b;
    // 成功读取2个整数才执行计算
    while (scanf("%d %d", &a, &b) == 2)
    {
        printf("a+b=%d\n", a + b);
    }
    return 0;
}

📝 总结

这篇博客覆盖了 C 语言核心语法的 “三大支柱”:数据类型(容器)、操作符(工具)、输入输出(交互)”。

如果这篇博客帮你避开了几个坑,欢迎点赞收藏!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值