import{_ as s,c as i,o as a,a6 as n}from"./chunks/framework.CZRoMP2i.js";const l="/c/assets/1.L8V3GBrc.png",p="/c/assets/2.nqdAY_P3.png",t="/c/assets/3.CceY8r_n.png",h="/c/assets/4.DHaUgOwj.png",k="/c/assets/5.CXGaq_zh.png",e="/c/assets/6.BrZYAEEl.png",r="/c/assets/7.DpCroFHv.png",d="/c/assets/8.Cr7P0Gji.png",E="/c/assets/9.NlBmD7pA.png",c="/c/assets/10.ZiBq6Pno.png",g="/c/assets/11.DAgmsf-w.png",F="/c/assets/12.B2iC37fw.png",y="/c/assets/14.BlE3ZFud.png",o="/c/assets/15.CBpay1zM.svg",u="/c/assets/16.B2zelVpk.svg",b="/c/assets/17.BW4hoq9o.svg",C="/c/assets/2.CdvhiwcU.png",m="/c/assets/3.D74t3-Xt.png",B="/c/assets/20.DdAZIfeP.png",A="/c/assets/21.B4Zfj2jX.png",D="/c/assets/22.IfpA0D5n.png",v="/c/assets/23.CfIzYazX.png",q="/c/assets/24.eHnZcbpI.png",f="/c/assets/25.BNoKlM4o.png",_="/c/assets/26.CMVtwrqr.png",x="/c/assets/27.CN19KJG7.png",z="/c/assets/28.BIhiJHjz.png",P="/c/assets/29.A_E4n4g8.png",w="/c/assets/30.Bv4qFbwF.png",I="/c/assets/31.IKaazo2J.png",N="/c/assets/32.CGTVELeO.png",T="/c/assets/33.Bz4_lEH0.gif",L="/c/assets/34.CcDWE4nn.png",O="/c/assets/35.B7y2_JVX.gif",S="/c/assets/36.Btcc3rs2.gif",U="/c/assets/37.CR4ARW8y.png",M="/c/assets/36.Btcc3rs2.gif",R="/c/assets/39.DOX3ymYP.gif",X="/c/assets/40.Cie9_tkP.gif",G="/c/assets/41.DLjH9Ges.png",is=JSON.parse('{"title":"第一章:数据类型(⭐)","description":"","frontmatter":{},"headers":[],"relativePath":"notes/01_c-basic/03_xdx/index.md","filePath":"notes/01_c-basic/03_xdx/index.md","lastUpdated":1723877358000}'),J={name:"notes/01_c-basic/03_xdx/index.md"},j=n('

第一章:数据类型(⭐)

1.1 概述

NOTE

普通变量和指针变量的相同点:

普通变量和指针变量的不同点:

NOTE

1.2 整数类型

1.2.1 概述

类型存储空间(内存空间)取值范围
unsigned short (无符号短整型)2 字节0 ~ 65,535 (2^16 - 1)
[signed] short(有符号短整型,默认)2 字节-32,768 (- 2^15) ~ 32,767 (2^15 -1)
类型存储空间(内存空间)取值范围
unsigned int(无符号整型)4 字节(通常)0 ~ 4294967295 (0 ~2^32 -1)
[signed] int(有符号整型,默认)4 字节(通常)-2147483648(- 2^31) ~ 2147483647 (2^31-1)
类型存储空间(内存空间)取值范围
unsigned long(无符号长整型)4 字节(通常)0 ~2^32 -1
[signed] long(有符号长整型,默认)4 字节(通常)- 2^31 ~ 2^31-1
类型存储空间(内存空间)取值范围
unsigned long long(无符号长整型)8 字节(通常)0 ~2^64 -1
[signed] long long(有符号长整型,默认)8 字节(通常)- 2^63 ~ 2^63-1

IMPORTANT

IMPORTANT

1.2.2 短整型(了解)

c
unsigned short x = 10 ; // 无符号短整型
c
short x = -10; // 有符号短整型

NOTE

c
#include <stdio.h>

int main() {

    // 定义有符号 short 类型
    signed short s1 = -100;

    printf("s1 = %hd \\n", s1); // s1 = -100

    // 定义无符号 short 类型
    unsigned short s2 = 100;
    printf("s2 = %hu \\n", s2); // s2 = 100

    // 定义 short 类型,默认是有符号
    short s3 = -200;
    printf("s3 = %hd \\n", s3); // s3 = -200

    return 0;
}
c
#include <stdio.h>

int main() {

    size_t s1 = sizeof(unsigned short);
    printf("unsigned short 的存储空间是 %zu 字节 \\n", s1); // 2

    size_t s2 = sizeof(signed short);
    printf("signed short 的存储空间是 %zu 字节 \\n", s2); // 2

    size_t s3 = sizeof(short);
    printf("short 的存储空间是 %zu 字节 \\n", s3); // 2

    return 0;
}
c
#include <limits.h>
#include <stdio.h>

int main() {

    printf("unsigned short 类型的范围是[0,%hu]\\n", USHRT_MAX); // [0,65535]
    printf("short 类型的范围是[%hd,%hd]\\n", SHRT_MIN,SHRT_MAX); // [-32768,32767]

    return 0;
}

1.2.3 整型

c
unsigned int x = 10 ; // 无符号整型
c
int x = -10; // 有符号整型

NOTE

c
#include <stdio.h>

int main() {

    // 定义有符号 int 类型
    signed int i1 = -100;

    printf("i1 = %d \\n", i1); // i1 = -100

    // 定义无符号 int 类型
    unsigned int i2 = 100;
    printf("i2 = %u \\n", i2); // i2 = 100

    // 定义 int 类型,默认是有符号
    short i3 = -200;
    printf("i3 = %d \\n", i3); // i3 = -200

    return 0;
}
c
#include <stdio.h>

int main() {

    size_t i1 = sizeof(unsigned int);
    printf("unsigned int 的存储空间是 %zu 字节 \\n", i1); // 4

    size_t i2 = sizeof(signed int);
    printf("signed int 的存储空间是 %zu 字节 \\n", i2); // 4

    size_t i3 = sizeof(int);
    printf("int 的存储空间是 %zu 字节 \\n", i3); // 4

    return 0;
}
c
#include <limits.h>
#include <stdio.h>

int main() {

    printf("unsigned int 类型的范围是[0,%u]\\n", UINT_MAX); // [0,4294967295]
    printf("int 类型的范围是[%d,%d]\\n", INT_MIN,INT_MAX); // [-2147483648,2147483647]

    return 0;
}

1.2.4 长整型(了解)

c
unsigned long x = 10 ; // 无符号长整型
c
long x = -10; // 有符号长整型

NOTE

c
#include <stdio.h>

int main() {

    // 定义有符号 long 类型
    signed long l1 = -100;

    printf("l1 = %ld \\n", l1); // l1 = -100

    // 定义无符号 long 类型
    unsigned long l2 = 100;
    printf("l2 = %lu \\n", l2); // l2 = 100

    // 定义 long 类型,默认是有符号
    long l3 = -200;
    printf("l3 = %ld \\n", l3); // l3 = -200

    return 0;
}
c
#include <stdio.h>

int main() {

    size_t l1 = sizeof(unsigned long);
    printf("unsigned long 的存储空间是 %zu 字节 \\n", l1); // 4

    size_t l2 = sizeof(signed long);
    printf("signed long 的存储空间是 %zu 字节 \\n", l2); // 4

    size_t l3 = sizeof(long);
    printf("long 的存储空间是 %zu 字节 \\n", l3); // 4

    return 0;
}
c
#include <limits.h>
#include <stdio.h>

int main() {

    printf("unsigned long 类型的范围是[0,%lu]\\n", ULONG_MAX); // [0,4294967295]
    printf("long 类型的范围是[%ld,%ld]\\n", LONG_MIN,LONG_MAX); // [-2147483648,2147483647]

    return 0;
}

1.2.5 长长整型(了解)

c
unsigned long long x = 10 ; // 无符号长长整型
c
long long x = -10; // 有符号长长整型

NOTE

c
#include <stdio.h>

int main() {

    // 定义有符号 long long 类型
    signed long long ll1 = -100;

    printf("ll1 = %lld \\n", ll1); // ll1 = -100

    // 定义无符号 long long 类型
    unsigned long long ll2 = 100;
    printf("ll2 = %llu \\n", ll2); // ll2 = 100

    // 定义 long long 类型,默认是有符号
    long long ll3 = -200;
    printf("ll3 = %lld \\n", ll3); // ll3 = -200

    return 0;
}
c
#include <stdio.h>

int main() {

    size_t ll1 = sizeof(unsigned long long);
    printf("unsigned long long 的存储空间是 %zu 字节 \\n", ll1); // 8

    size_t ll2 = sizeof(signed long long);
    printf("signed long long 的存储空间是 %zu 字节 \\n", ll2); // 8

    size_t ll3 = sizeof(long long);
    printf("long long 的存储空间是 %zu 字节 \\n", ll3); // 8

    return 0;
}
c
#include <limits.h>
#include <stdio.h>

int main() {

    printf("unsigned long long 类型的范围是[0,%llu]\\n", ULLONG_MAX); // [0,18446744073709551615]
    printf("long long 类型的范围是[%lld,%lld]\\n", LLONG_MIN,LLONG_MAX); // [-9223372036854775808,9223372036854775807]

    return 0;
}

1.2.6 字面量后缀

c
int num1 = 100; // 100 就是字面量
c
long num2 = 100L; // 100L 就是字面量
c
long long num3 = 100LL; // 100LL 就是字面量

NOTE

c
#include <stdio.h>

int main() {

    int num = 100;
    printf("num = %d\\n", num); // num = 100

    long num2 = 100L;
    printf("num2 = %ld\\n", num2); // num2 = 100

    long long num3 = 100LL;
    printf("num3 = %lld\\n", num3); // num3 = 100

    unsigned int num4 = 100U;
    printf("num4 = %u\\n", num4); // num4 = 100

    unsigned long num5 = 100LU;
    printf("num5 = %lu\\n", num5); // num5 = 100

    unsigned long long num6 = 100ULL;
    printf("num6 = %llu\\n", num6); // num6 = 100

    return 0;
}

1.2.7 精确宽度类型

NOTE

类型名称含义
int8_t8 位有符号整数
int16_t16 位有符号整数
int32_t32 位有符号整数
int64_t64 位有符号整数
uint8_t8 位无符号整数
uint16_t16 位无符号整数
uint32_t32 位无符号整数
uint64_t64 位无符号整数

NOTE

上面的这些类型都是类型别名,编译器会指定它们指向的底层类型,如:在某个系统中,如果 int 类型是 32 位,那么 int32_t 就会指向 int ;如果 long 类型是 32 位,那么 int32_t 就会指向 long。

c
#include <stdio.h>
#include <stdint.h>

int main() {

    // 变量 x32 声明为 int32_t 类型,可以保证是 32 位(4个字节)的宽度。
    int32_t x32 = 45933945;
    printf("x32 = %d \\n", x32); // x32 = 45933945

    return 0;
}

1.2.8 sizeof 运算符

c
sizeof(表达式)

NOTE

c
#include <stdio.h>
#include <stddef.h>

int main() {

    size_t s = sizeof(int);

    printf("%zu \\n", s); // 4

    return 0;
}
c
#include <stdio.h>
#include <stddef.h>

int main() {

    int num = 10;

    size_t s = sizeof(num);

    printf("%zu \\n", s); // 4

    return 0;
}
c
#include <stdio.h>
#include <stddef.h>

int main() {

    size_t s = sizeof(10);

    printf("%zu \\n", s); // 4

    return 0;
}

1.2.9 数值溢出

NOTE

NOTE

在实际开发中,选择合适的数据类型,以避免数值溢出问题!!!

c
#include <limits.h>
#include <stdio.h>

int main() {

    unsigned short s1 = USHRT_MAX + 1;
    printf("无符号的上溢出 = %hu \\n", s1); // 0

    unsigned short s2 = 0 - 1;
    printf("无符号的下溢出 = %hu \\n", s2); // 65535

    return 0;
}
c
#include <limits.h>
#include <stdio.h>

int main() {

    short s1 = SHRT_MAX + 1;
    printf("有符号的上溢出 = %hd \\n", s1); // -32768

    short s2 = SHRT_MIN - 1;
    printf("有符号的下溢出 = %hd \\n", s2); // 32767

    return 0;
}

1.3 浮点类型

1.3.1 概述

NOTE

类型存储大小值的范围有效小数位数
float(单精度)4 字节1.2E-38 ~ 3.4E+386 ~ 9
double(双精度)8 字节2.3E-308 ~ 1.7E+30815 ~ 18
long double(长双精度)16 字节3.4E-4932 ~ 1.2E+493218 或更多

NOTE

1.3.2 格式占位符

c
#include <stdio.h>

int main() {

    float f1 = 10.0;

    printf("f1 = %f \\n", f1); // f1 = 10.000000
    printf("f1 = %.2f \\n", f1); // f1 = 10.00

    return 0;
}
c
#include <stdio.h>

int main() {

    double d1 = 13.14159265354;

    printf("d1 = %lf \\n", d1); // d1 = 13.141593
    printf("d1 = %.2lf \\n", d1); // d1 = 13.14

    return 0;
}
c
#include <stdio.h>

int main() {

    long double d1 = 13.14159265354;

    printf("d1 = %LF \\n", d1); // d1 = 13.141593
    printf("d1 = %.2LF \\n", d1); // d1 = 13.14

    return 0;
}
c
#include <stdio.h>

int main() {

    float       f1 = 3.1415926;
    double      d2 = 3.14e2;

    printf("f1 = %.2f \\n", f1); // f1 = 3.14
    printf("f1 = %.2e \\n", f1); // f1 = 3.14e+00
    printf("d2 = %.2lf \\n", d2); // d2 = 314.00
    printf("d2 = %.2e \\n", d2); // d2 = 3.14e+02

    return 0;
}

1.3.3 字面量后缀

c
#include <stdio.h>

int main() {

    float       f1 = 3.1415926f;
    double      d2 = 3.1415926;
    long double d3 = 3.1415926L;

    printf("f1 = %.2f \\n", f1); // f1 = 3.14
    printf("d2 = %.3lf \\n", d2); // d2 = 3.142
    printf("d3 = %.4Lf \\n", d3); // d3 = 3.1416

    return 0;
}

1.3.4 类型占用的内存大小(存储空间)

c
#include <stdio.h>

int main() {

    printf("float 的存储空间是 %zu 字节 \\n", sizeof(float)); // 4
    printf("double 的存储空间是 %zu 字节 \\n", sizeof(double)); // 8
    printf("long double 的存储空间是 %zu 字节 \\n", sizeof(long double)); // 16

    return 0;
}

1.3.5 类型的取值范围

c
#include <float.h>
#include <stdio.h>

int main() {

    printf("float 的取值范围是:[%.38f, %f] \\n", FLT_MIN, FLT_MAX);
    printf("double 的取值范围是:[%lf, %lf] \\n", DBL_MIN, DBL_MAX);
    printf("double 的取值范围是:[%Lf, %Lf] \\n", LDBL_MIN, LDBL_MAX);

    return 0;
}

1.4 字符类型

1.4.1 概述

NOTE

转义字符说明
\\b退格
\\n换行符
\\r回车符
\\t制表符
\\"双引号
\\'单引号
\\\\反斜杠
...

1.4.2 格式占位符

c
#include <stdio.h>

int main() {

    char c = '&';

    printf("c = %c \\n", c); // c = &

    char c2 = 'a';
    printf("c2 = %c \\n", c2); // c2 = a

    char c3 = 'A';
    printf("c3 = %c \\n", c3); // c3 = A

    return 0;
}

1.4.3 类型占用的内存大小(存储空间)

c
#include <stdio.h>

int main() {

    printf("char 的存储空间是 %d 字节\\n", sizeof(char)); // 1 
    printf("unsigned char 的存储空间是 %d 字节\\n", sizeof(unsigned char)); // 1

    return 0;
}

1.4.4 类型的取值范围

c
#include <limits.h>
#include <stdio.h>

int main() {

    printf("char 范围是[%d,%d] \\n", CHAR_MIN,CHAR_MAX); // [-128,127]
    printf("unsigned char 范围是[0,%d]\\n", UCHAR_MAX); // [0,255]

    return 0;
}

1.4.5 字符类型的本质

c
#include <limits.h>
#include <stdio.h>

int main() {
    // char 类型字面量需要使用单引号包裹
    char a1 = 'A';
    char a2 = '9';
    char a3 = '\\t';
    printf("c1=%c, c3=%c, c2=%c \\n", a1, a3, a2);

    // char 类型本质上整数可以进行运算
    char b1 = 'b';
    char b2 = 101;
    printf("%c->%d \\n", b1, b1);
    printf("%c->%d \\n", b2, b2);
    printf("%c+%c=%d \\n", b1, b2, b1 + b2);

    // char 类型取值范围
    unsigned char c1 = 200; // 无符号 char 取值范围 0 ~255
    signed char   c2 = 200; // 有符号 char 取值范围 -128~127,c2会超出范围
    char          c3 = 200; // 当前系统,char 默认是 signed char
    printf("c1=%d, c2=%d, c3=%d", c1, c2, c3);

    return 0;
}

1.5 布尔类型

1.5.1 概述

1.5.2 早期的布尔类型

c
#include <stdio.h>

int main() {
	// 禁用 stdout 缓冲区
    setbuf(stdout, NULL);
    
    // 使用整型来表示真和假两种状态
    int handsome = 0; 
    printf("帅不帅[0 丑,1 帅]: ");
    scanf("%d", &handsome);

    if (handsome) {
        printf("你真的很帅!!!");
    } else {
        printf("你真的很丑!!!");
    }

    return 0;
}

1.5.3 宏定义的布尔类型

c
#include <stdio.h>

// 宏定义
#define BOOL int
#define TRUE 1
#define FALSE 0

int main() {
    // 禁用 stdout 缓冲区
    setbuf(stdout, NULL);
    
    BOOL handsome = 0;
    printf("帅不帅[FALSE 丑,TRUE 帅]: ");
    scanf("%d", &handsome);

    if (handsome) {
        printf("你真的很帅!!!");
    } else {
        printf("你真的很丑!!!");
    }

    return 0;
}

1.5.4 C99 标准中的布尔类型

c
#include <stdio.h>

int main() {
    // 禁用 stdout 缓冲区
    setbuf(stdout, NULL);

    int   temp; // 使用 int 类型的变量临时存储输入
    _Bool handsome = 0;
    printf("帅不帅[0 丑,1 帅]: ");
    scanf("%d", &temp);

    // 将输入值转换为 _Bool 类型
    handsome = (temp != 0);

    if (handsome) {
        printf("你真的很帅!!!");
    } else {
        printf("你真的很丑!!!");
    }

    return 0;
}

1.5.5 C99 标准头文件中的布尔类型(推荐)

NOTE

在 C++、Java 等高级编程语言中是有 boolean 类型的关键字的。

c
#include <stdbool.h>
#include <stdio.h>
#include <string.h>

int main() {

    // 禁用 stdout 缓冲区
    setbuf(stdout, NULL);

    char input[10];
    bool handsome = false;

    printf("帅不帅[false 丑,true 帅]: ");
    scanf("%s", input); // 使用 %s 读取字符串

    // 将输入字符串转换为布尔值
    if (strcmp(input, "true") == 0) {
        handsome = true;
    } else if (strcmp(input, "false") == 0) {
        handsome = false;
    } else {
        printf("无效输入!\\n");
        return 1;
    }

    if (handsome) {
        printf("你真的很帅!!!");
    } else {
        printf("你真的很丑!!!");
    }

    return 0;
}

1.6 数据类型转换

1.6.1 概述

1.6.2 自动类型转换(隐式转换)

1.6.2.1 运算过程中的自动类型转换

WARNING

最好避免无符号整数与有符号整数的混合运算,因为这时 C 语言会自动将 signed int 转为 unsigned int ,可能不会得到预期的结果。

c
#include <stdio.h>

/**
 * 不同的整数类型混合运算时,宽度较小的类型会提升为宽度较大的类型,比如 short 转为 int ,int 转为 long 等。
 */
int main() {

    short s1 = 10;

    int i = 20;

    // s1 是 short 类型,i 是 int 类型,当 s1 和 i 运算的时候,会自动转为 int 类型后,然后再计算。
    int result = s1 + i;

    printf("result = %d \\n", result);

    return 0;
}
c
#include <stdio.h>


int main() {

    int          n2 = -100;
    unsigned int n3 = 20;

    // n2 是有符号,n3 是无符号,当 n2 和 n3 运算的时候,会自动转为无符号类型后,然后再计算。
    int result = n2 + n3;

    printf("result = %d \\n", result);

    return 0;
}
c
#include <stdio.h>

/**
* 不同的浮点数类型混合运算时,宽度较小的类型转为宽度较大的类型,比如 float 转为 double ,double 转为 long double 。
*/
int main() {

    float  f1 = 1.25f;
    double d2 = 4.58667435;

    // f1 是 float 类型,d2 是 double 类型,当 f1 和 d2 运算的时候,会自动转为 double 类型后,然后再计算。
    double result = f1 + d2;

    printf("result = %.8lf \\n", result);

    return 0;
}
c
#include <stdio.h>

/**
 * 整型与浮点型运算,整型转为浮点型
 */
int main() {

    int    n4 = 10;
    double d3 = 1.67;

    // n4 是 int 类型,d3 是 double 类型,当 n4 和 d3 运算的时候,会自动转为 double 类型后,然后再计算。
    double result = n4 + d3;

    printf("%.2lf", result);

    return 0;
}

1.6.2.2 赋值时的自动类型转换

WARNING

C 语言在检查类型匹配方面不太严格,最好不要养成这样的习惯。

c
#include <stdio.h>

int main() {

    // 赋值:窄类型赋值给宽类型
    int    a1 = 10;
    double a2 = a1;
    printf("a2: %.2f\\n", a2); // a2: 10.00

    // 转换:将宽类型转换为窄类型
    double b1 = 10.5;
    int    b2 = b1;
    printf("b2: %d\\n", b2); // b2: 10

    return 0;
}

1.6.3 强制类型转换

c
数据类型 变量名 = (类型名)变量、常量或表达式;

CAUTION

强制类型转换可能会导致精度损失!!!

c
#include <stdio.h>

int main(){
    double d1 = 1.934;
    double d2 = 4.2;
    int num1 = (int)d1 + (int)d2;         // d1 转为 1,d2 转为 4,结果是 5
    int num2 = (int)(d1 + d2);            // d1+d2 = 6.134,6.134 转为 6
    int num3 = (int)(3.5 * 10 + 6 * 1.5); // 35.0 + 9.0 = 44.0 -> int = 44

    printf("num1=%d \\n", num1);
    printf("num2=%d \\n", num2);
    printf("num3=%d \\n", num3);

    return 0;
}

1.7 再谈数据类型

NOTE

这些存储单元中,存储的都是 0 和 1 这样的数据,因为计算机只能识别二进制数。

NOTE

之所以,要给每个存储单元加上内存地址,就是为了加快数据的存取速度,可以类比生活中的字典以及快递单号

c
int num = 10;

NOTE

上述的代码其实透露了三个重要的信息:

NOTE

IMPORTANT

第二章:运算符(⭐)

2.1 概述

NOTE

掌握一个运算符,需要关注以下几个方面:

2.2 算术运算符

运算符描述操作数个数组成的表达式的值副作用
+正号1操作数本身
-负号1操作数符号取反
+加号2两个操作数之和
-减号2两个操作数之差
*乘号2两个操作数之积
/除号2两个操作数之商
%取模(取余)2两个操作数相除的余数
++自增1操作数自增前或自增后的值
--自减1操作数自减前或自减后的值

NOTE

自增和自减:

c
#include <stdio.h>

int main() {

    int x  = 12;
    int x1 = -x, x2 = +x;

    int y  = -67;
    int y1 = -y, y2 = +y;

    printf("x1=%d, x2=%d \\n", x1, x2); // x1=-12, x2=12
    printf("y1=%d, y2=%d \\n", y1, y2); // y1=67, y2=-67

    return 0;
}
c
#include <stdio.h>

int main() {

    int a = 5;
    int b = 2;

    printf("%d + %d = %d\\n", a, b, a + b); // 5 + 2 = 7
    printf("%d - %d = %d\\n", a, b, a - b); // 5 - 2 = 3
    printf("%d × %d = %d\\n", a, b, a * b); // 5 × 2 = 10
    printf("%d / %d = %d\\n", a, b, a / b); // 5 / 2 = 2
    printf("%d %% %d = %d\\n", a, b, a % b); // 5 % 2 = 1

    return 0;
}
c
#include <stdio.h>

int main() {

    int res1 = 10 % 3;
    printf("10 %% 3 = %d\\n", res1); // 10 % 3 = 1

    int res2 = -10 % 3;
    printf("-10 %% 3 = %d\\n", res2); // -10 % 3 = -1

    int res3 = 10 % -3;
    printf("10 %% -3 = %d\\n", res3); // 10 % -3 = 1

    int res4 = -10 % -3;
    printf("-10 %% -3 = %d\\n", res4); // -10 % -3 = -1

    return 0;
}
c
#include <stdio.h>

int main() {

    int i1 = 10, i2 = 20;
    int i  = i1++;
    printf("i = %d\\n", i); // i = 10
    printf("i1 = %d\\n", i1); // i1 = 11

    i = ++i1;
    printf("i = %d\\n", i); // i = 12
    printf("i1 = %d\\n", i1); // i1 = 12

    i = i2--;
    printf("i = %d\\n", i); // i = 20
    printf("i2 = %d\\n", i2); // i2 = 19

    i = --i2;
    printf("i = %d\\n", i); // i = 18
    printf("i2 = %d\\n", i2); // i2 = 18

    return 0;
c
#include <stdio.h>

/*
  随意给出一个整数,打印显示它的个位数,十位数,百位数的值。
  格式如下:
    数字xxx的情况如下:
    个位数:
    十位数:
    百位数:
  例如:
    数字153的情况如下:
    个位数:3
    十位数:5
    百位数:1
 */
int main() {

    int num = 153;

    int bai = num / 100;
    int shi = num % 100 / 10;
    int ge  = num % 10;
    printf("百位为:%d \\n", bai);
    printf("十位为:%d \\n", shi);
    printf("个位为:%d \\n", ge);

    return 0;
}

2.3 关系运算符(比较运算符)

运算符描述操作数个数组成的表达式的值副作用
==相等20 或 1
!=不相等20 或 1
<小于20 或 1
>大于20 或 1
<=小于等于20 或 1
>=大于等于20 或 1

NOTE

c
#include <stdio.h>

int main() {

    int a = 8;
    int b = 7;

    printf("a > b 的结果是:%d \\n", a > b); // a > b 的结果是:1
    printf("a >= b 的结果是:%d \\n", a >= b); // a >= b 的结果是:1
    printf("a < b 的结果是:%d \\n", a < b); // a < b 的结果是:0
    printf("a <= b 的结果是:%d \\n", a <= b); // a <= b 的结果是:0
    printf("a == b 的结果是:%d \\n", a == b); // a == b 的结果是:0
    printf("a != b 的结果是:%d \\n", a != b); // a != b 的结果是:1

    return 0;
}

2.4 逻辑运算符

运算符描述操作数个数组成的表达式的值副作用
&&逻辑与20 或 1
||逻辑或20 或 1
!逻辑非20 或 1
aba && ba || b!a
1(真)1(真)1(真)1(真)0(假)
1(真)0(假)0(假)1(真)0(假)
0(假)1(真)0(假)1(真)1(真)
0(假)0(假)0(假)0(假)1(真)

NOTE

c
#include <stdio.h>

int main() {

    int a = 0;
    int b = 0;

    printf("请输入整数a的值:");
    scanf("%d", &a);
    printf("请输入整数b的值:");
    scanf("%d", &b);

    if (a > b) {
        printf("%d > %d", a, b);
    } else if (a < b) {
        printf("%d < %d", a, b);
    } else {
        printf("%d = %d", a, b);
    }

    return 0;
}
c
#include <stdio.h>

// 短路现象
int main() {

    int i = 0;
    int j = 10;
    if (i && j++ > 0) {
        printf("床前明月光\\n"); // 这行代码不会执行
    } else {
        printf("我叫郭德纲\\n");
    }
    printf("%d \\n", j); //10

    return 0;
}
c
#include <stdio.h>

// 短路现象

int main() {

    int i = 1;
    int j = 10;
    if (i || j++ > 0) {
        printf("床前明月光 \\n");
    } else {
        printf("我叫郭德纲 \\n"); // 这行代码不会被执行
    }
    printf("%d\\n", j); //10

    return 0;
}

2.5 赋值运算符

运算符描述操作数个数组成的表达式的值副作用
==赋值2左边操作数的值
+=相加赋值2左边操作数的值
-=相减赋值2左边操作数的值
*=相乘赋值2左边操作数的值
/=相除赋值2左边操作数的值
%=取余赋值2左边操作数的值
<<=左移赋值2左边操作数的值
>>=右移赋值2左边操作数的值
&=按位与赋值2左边操作数的值
^=按位异或赋值2左边操作数的值
|=按位或赋值2左边操作数的值

NOTE

c
#include <stdio.h>

int main() {

    int a = 3;
    a += 3; // a = a + 3
    printf("a = %d\\n", a); // a = 6

    int b = 3;
    b -= 3; // b = b - 3
    printf("b = %d\\n", b); // b = 0

    int c = 3;
    c *= 3; // c = c * 3
    printf("c = %d\\n", c); // c = 9

    int d = 3;
    d /= 3; // d = d / 3
    printf("d = %d\\n", d); // d = 1

    int e = 3;
    e %= 3; // e = e % 3
    printf("e = %d\\n", e); // e = 0

    return 0;
}

2.6 位运算符(了解)

2.6.1 概述

运算符描述操作数个数运算规则副作用
&按位与2两个二进制位都为 1 ,结果为 1 ,否则为 0 。
|按位或2两个二进制位只要有一个为 1(包含两个都为 1 的情况),结果为 1 ,否则为 0 。
^按位异或2两个二进制位一个为 0 ,一个为 1 ,结果为 1,否则为 0 。
~按位取反2将每一个二进制位变成相反值,即 0 变成 1 , 1 变 成 0 。
<<二进制左移2将一个数的各二进制位全部左移指定的位数,左 边的二进制位丢弃,右边补 0。
>>二进制右移2将一个数的各二进制位全部右移指定的位数,正数左补 0,负数左补 1,右边丢弃。

NOTE

操作数在进行位运算的时候,以它的补码形式计算!!!

2.6.2 输出二进制位

c
#include <stdio.h>

/**
 * 获取指定整数的二进制表示
 * @param num 整数
 * @return 二进制表示的字符串,不包括前导的 '0b' 字符
 */
char* getBinary(int num) {
    static char binaryString[33];
    int         i, j;

    for (i = sizeof(num) * 8 - 1, j = 0; i >= 0; i--, j++) {
        const int bit   = (num >> i) & 1;
        binaryString[j] = bit + '0';
    }

    binaryString[j] = '\\0';
    return binaryString;
}

int main() {

    int a = 17;
    int b = -12;

    printf("整数 %d 的二进制表示:%s \\n", a, getBinary(a));
    printf("整数 %d 的二进制表示:%s \\n", b, getBinary(b));

    return 0;
}

2.6.3 按位与

2.6.4 按位或

2.6.5 按位异或

NOTE

按位异或的场景有:

2.6.6 按位取反

2.6.7 二进制左移

2.6.8 二进制右移

NOTE

2.7 三元运算符

c
条件表达式 ? 表达式1 : 表达式2 ;

NOTE

c
#include <stdio.h>

int main() {

    int m      = 110;
    int n      = 20;
    int result = m > n ? m : n;
    printf("result = %d\\n", result); // result = 110

    return 0;
}

2.8 运算符优先级

优先级运算符名称或含义结合方向
1[]数组下标➡️(从左到右)
()圆括号
.成员选择(对象)
->成员选择(指针)
2-负号运算符⬅️(从右到左)
(类型)强制类型转换
++自增运算符
--自减运算符
*取值运算符
&取地址运算符
!逻辑非运算符
~按位取反运算符
sizeof长度运算符
3/➡️(从左到右)
*
%余数(取模)
4+➡️(从左到右)
-
5<<左移➡️(从左到右)
>>右移
6>大于➡️(从左到右)
>=大于等于
<小于
<=小于等于
7==等于➡️(从左到右)
!=不等于
8&按位与➡️(从左到右)
9^按位异或➡️(从左到右)
10|按位或➡️(从左到右)
11&&逻辑与➡️(从左到右)
12||逻辑或➡️(从左到右)
13?:条件运算符⬅️(从右到左)
14=赋值运算符⬅️(从右到左)
/=除后赋值
*=乘后赋值
%=取模后赋值
+=加后赋值
-=减后赋值
<<=左移后赋值
>>=右移后赋值
&=按位与后赋值
^=按位异或后赋值
|=按位或后赋值
15,逗号运算符➡️(从左到右)

WARNING

第三章:附录

3.1 字符集和字符集编码

3.3.1 概述

NOTE

ASCII(美国信息交换标准代码)是最早期和最简单的字符集之一,它只包括了英文字母、数字和一些特殊字符,共 128 个字符。每个字符都分配给了一个从 0 到 127 的数字。

NOTE

ASCII 编码方案定义了如何将 ASCII 字符集中的每个字符表示为 7 位的二进制数字。例如:大写字母'A'在 ASCII 编码中表示为二进制的1000001,十进制的 65

3.3.2 ASCII 编码

NOTE

shell
man ascii

NOTE

3.3.3 Unicode 编码

',348),H=[j];function V(Z,K,W,Y,$,Q){return a(),i("div",null,H)}const as=s(J,[["render",V]]);export{is as __pageData,as as default};