C语言基础

184 阅读21分钟

C语言

常量

#define 常量名 常量值

#include <stdio.h>#define PI 3.14 // 定义常量 PI,常量值 3.14int main()
{
    double area;
    double r = 1.2;
    area = PI * r * r;
    printf("面积 : %.2f", area);
​
    return 0;
}

const 数据类型 常量名 = 常量值;

#include <stdio.h>const double PI = 3.14; // const 定义常量时,需要加分号int main()
{
    double area;
    double r = 1.2;
    area = PI * r * r;
    printf("面积 : %.2f", area);
​
    return 0;
}

两者的求别

#define是预处理指令,在编译前运行;const是关键字,在编译过程中执行,

#define定义常量不用指定类型,不进行类型检查,只是简单地文本替换;const定义常量需指定数据类型,会进行类型检查,类型安全性更强。

进制

进制的种类

  • 二进制:0、1,满2进1

  • 十进制:0 - 9,满10进1

  • 十六进制:0 - 9及A-F,满16进1;A-F可大写,可小写

    二进制十进制十六进制
    000
    111
    1022
    1133
    10044
    10155
    11066
    11177
    100088
    100199
    101010A
    101111B
    110012C
    110113D
    111014E
    111115F
    100001610
    100011711

C语言中进制表示

  • 二进制:以0b或0B开头表示
  • 十进制:正常数字表示
  • 十六进制:以0x或0X开头表示
#include <stdio.h>int main()
{
    int num1 = 0b10; // 二进制
    int num2 = 210;  // 十进制
    int num3 = 0x1f; // 十六进制
​
    printf("num1=%d \n", num1);
    printf("num1=%d \n", num2);
    printf("num1=%d \n", num3);
​
    return 0;
}
结果
    num1=2 
    num1=210
    num1=31

输出格式

  • 使用格式占位符可以将整数以不同进制形式输出

%d:十进制整数

%x:十六进制整数

%#x:前缀为0x的十六进制整数

%#X:前缀为0X的十六进制整数

进制之间的转换

二进制转换十进制

十进制转换二进制

十六进制和十进制转换

将该数不断除以16,直到商为0为止,然后将每步得到的余数倒过来,就是对应的十六进制。

十进制转换十六进制

将该数不断除以16,直到商为0为止,然后将每步得到的余数倒过来,就是对应的十六进制。

机器数和真值

机器数:一个数在计算机的存储形式是二进制数,我们称这些二进制数为机器数,机器数是有符号的,用机器数的最高位存放符号位,0表示正数,1表示负数。 真值:因为机器数带有符号位,所以机器数的形式值不等于其真实表示的值(真值),以机器数10000001为例,其真正表示的值(首位为符号位)为-1,而形式值(首位就是代表1)为129;因此将带符号的机器数的真正表示的值称为机器数的真值。

原码、反码、补码

1.原码 *原码的表示与机器数真值表示的一样,即用第一位表示符号,其余位表示数值。

  • 正数的原码:就是它对应的二进制数。
  • 负数的原码:它的绝对值对应的二进制数,且最左边位变为1。
  • 0的原码:仍然是0 +1 原码:[ 0000 0001 ] -1 原码:[ 1000 0001 ]

2.反码

  • 正数的反码:和原码相同
  • 负数的反码:在其原码的基础上,符号位不变,其余各位取反
  • 0的反码:仍然是0

+1 原码:[ 0000 0001 ] 反码:[ 0000 0001 ]

-1 原码: [ 1000 0001 ] 反码:[ 1111 1110 ]

反码通常是用来由原码求补码或者由补码求原码的过渡码。

3.补码

  • 正数的补码:和原码、反码相同
  • 负数的补码:反码的基础上加1
  • 0的补码:仍然是0 +1 原码:[ 0000 0001 ] 反码:[ 0000 0001 ] 补码:[ 0000 0001 ] -1 原码:[ 1000 0001 ] 反码:[ 1111 1110 ] 补码:[ 1111 1111 ]

总结

  • 正数的原码、反码、补码都一样,三码合一
  • 负数的反码:它的原码符号位不变,其它位取反(0 -> 1,1 -> 0);负数的补码:它的反码+1
  • 0的反码,补码都是0

数据类型

整数类型

整型的类型

  • 存储大小的单位

bit(位):计算机中最小的存储单位,表示一个二进制位。

byte(字节):计算机中基本的存储单元,1 byte = 8 bit。

字面量后缀

字面量是源代码中一个固定值的表示法,用于直接表示数据。

  • 一个整型字面量默认是int类型。
  • 表示long类型字面量,添加后缀l或L。
  • 表示long long 类型字面量,添加后缀ll或LL。
  • 表示无符号整数字面量,添加后缀 u 或 U, u 和 l 可以结合使用,不分先后,如 ul(无符号long类型)、ULL(无符号 long long类型),lu(无符号 long 类型) 等。

格式占位符

  • %d对应int,%u对应unsigned int。

  • %ld对应long,%lu对应unsigned long。

  • %lld对应long long,%llu对应unsigned long long。

    #include <stdio.h>
    ​
    int main()
    {
        // short 类型
        short a1 = 10;  // 等同于 signed short a1 = 10;
        short a2 = -10; // 等同于 signed short a1 = -10;
        // unsigned short a3 = -20;
        unsigned short a3 = 20;
        printf("a1=%d; a2=%d; a3=%d \n", a1, a2, a3); // a1=10; a2=-10; a3=20
    ​
        // int 类型
        int b1 = 100;  // 等同于 signed int a1 = 100;
        int b2 = -100; // 等同于 signed int a1 = -100;
        unsigned int b3 = 200u;
        unsigned b4 = 300U;                                      // 等同于  unsigned int b4 = 300U;
        printf("b1=%d; b2=%d; b3=%d; b4=%d \n", b1, b2, b3, b4); // b1=100; b2=-100; b3=200; b4=300
    ​
        // long 类型
        long c1 = 1000l;   // 等同于 signed long c1 = 1000l;
        long c2 = -1000L; // 等同于 signed long c2 = -1000L;
        unsigned long c3 = 2000ul;
        printf("c1=%ld; c2=%ld; c3=%ld \n", c1, c2, c3); // c1=100; c2=-1000; c3=2000
    ​
        // long long 类型
        long long d1 = 10000ll;  // 等同于 signed long long d1 = 10000ll;
        long long d2 = -10000LL; // 等同于 signed long long d2 = -10000LL;
        unsigned long long d3 = 20000ULL;
        printf("d1=%lld; d2=%lld; d3=%lld \n", d1, d2, d3); // d1=10000; d2=-10000; d3=20000
    ​
        return 0;
    }
    结果:
        a1=10; a2=-10; a3=20
        b1=100; b2=-100; b3=200; b4=300
        c1=100; c2=-1000; c3=2000
        d1=10000; d2=-10000; d3=20000
    

精准宽度类型

C 语言的整数类型 (short、int、long) 在不同计算机上,占用的字节宽度可能是不一样的。程序员有时需要精准的字节宽度,以提高代码的可移植性,尤其是嵌入式开发中,使用精确宽度类型可以确保代码在各种平台上的一致性。

标准库的头文件 <stdint.h> 中定义了一些新的类型别名,如下:

类型名称含义
int8_t8 位有符号整数
int16_t16 位有符号整数
int32_t32 位有符号整数
int64_t64 位有符号整数
uint8_t8 位无符号整数
uint16_t16 位无符号整数
uint32_t32 位无符号整数
uint64_t64 位无符号整数
#include <stdio.h>
#include <stdint.h>
int main()
{
    // 变量 x32 声明为 int32_t 类型,可以保证是32位(4个字节)的宽度。
    int32_t x32 = 45933945; 
    printf("x32=%d\n", x32);
    return 0;
}
x32=45933945

浮点类型

类型存储大小值范围有效小数位数
float 单精度4字节1.2E-38到3.4E+386-9
double双精度2.3E-38到1.7E+30815-18
long double长双精度32位:10字节 64位:16字节32位:与double相同或更大 64位:3.4E-4932到1.2E+493218或更大

浮点数注意事项

两种表示方式

  • 十进制表示:5.12、512.0f、.512(0.512可以省略0)
  • 科学计数法表示:5.12e2、5.12E-2

字面量后缀

  • 浮点数字面量默认是double型。
  • 表示float类型字面量,须加后缀 f 或 F。
  • 如果需要表示long double类型字面量,需加后缀 l 或 L。

格式占位符

  • %f 是浮点类型的格式占位符,float类型转换为double类型来处理;默认保存6位小数,%.2f表示保留2位小数。
  • %lf在printf中和%f意思相同,也对应double类型,默认保存6位小数,也可以指定保留几位小数,但是在scanf中输入float类型数据时使用 %f,输入double类型数据使用 %lf
  • %Lf对应long double 类型,默认保存6位小数,也可以指定,输入输出long double类型都必须使用%LF占位符。
  • %e对应科学计数法的浮点数,可以指定小数位数。

字符类型

字符类型char可以表示一个数字,一个字母,一个符号。

  • char类型的字面量用单引号括起来的单个字符。

  • 可以使用转义符\表示特殊含义的字符。

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

格式占位符

使用%c表示char类型。

字符类型的本质

  • char类型本质上是一个整数,是ASCII玛中对应的数字,存储长度是1个字节,char类型也可以进行数字运算。

  • 字符型同样分为signed char(有符号类型),unsigned char(无符号类型,signed char 取值-128-到127,无符号类型0-255。

#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;
}
结果:
c1=A, c3=       , c2=9
b -> 98
e -> 101
b + e = 199
c1=200, c2=-56, c3=-56

布尔类型

布尔值用于表示真假两种状态,常用于逻辑运算和条件判断。

布尔类型的三种方式

  • 借助C语言的宏定义
#include <stdio.h>// 宏定义
#define BOOL int
#define TURE 1
#define FALSE 0int main()
{
    // 使用整型表示真假两种状态
    // int isPass = 0;
    // int isOk = 1;
​
    // 借助于宏定义
    BOOL isPass = FALSE;
    BOOL isOk = TURE;
​
    printf("isPass=%d, isOk=%d \n", isPass, isOk);
​
    if (isPass)
    {
        printf("Pass");
    }
​
    if (isOk)
    {
        printf("Ok");
    }
​
    return 0;
}
输出结果
isPass=0, isOk=1 
Ok
  • C99标准提供了Bool 型, Bool仍是整数类型,但与一般整型不同的是,_Bool变量只能赋值为0或1,非0的值都会被存储为1。
#include <stdio.h>int main()
{
    // 使用 _BOOL 类型
    _Bool isPass = 0;
    //_Bool isOk = 1;
    _Bool isOk = -4;
​
    printf("isPass=%d, isOk=%d \n", isPass, isOk);
​
    if (isPass)
    {
        printf("Pass");
    }
​
    if (isOk)
    {
        printf("Ok");
    }
​
    return 0;
}
结果
isPass=0, isOk=1 
Ok
  • (1)C99标准还提供了一个头文件 <stdbool.h> 定义了bool代表_Bool,true代表1,false代表0。
#include <stdio.h>
#include <stdbool.h>int main()
{
    bool isPass = false;
    bool isOk = true;
​
    printf("isPass=%d, isOk=%d \n", isPass, isOk);
​
    if (isPass)
    {
        printf("Pass");
    }
​
    if (isOk)
    {
        printf("Ok");
    }
​
    return 0;
}
结果
isPass=0, isOk=1 
Ok

获取数据的存储大小

sizeof可以获取数据类型或变量、字面量的存储大小,单位是字节,sizeof返回一个size_t类型的无符号整数值,格式占位符是%zu。

数据类型的转换

转换规则

  • 不同类型整数进行运算,窄类型整数自动转换为宽类型整数。
  • 不同类型浮点数进行运算,精度小的类型自动转换为精度大的类型。
  • 整数与浮点数进行运算,整数自动转换为浮点数。

强制类型转换

(类型名)变量、常量或表达式

#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;
}
结果
num1=5 
num2=6 
num3=44

算术运算符

自增自减

  • 自增、自减运算符可以写在操作数的前面也可以写在操作数后面,不论前面还是后面,对操作数的副作用是一致的。
  • 自增、自减运算符在前在后,对于表达式的值是不同的。 如果运算符在前,表达式的值是操作数自增、自减之后的值;如果运算符在后,表达式的值是操作数自增、自减之前的值。
#include <stdio.h>

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

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

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

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

    return 0;
}
输出结果:
10
11
12
12
20
19
18
18

逻辑运算符

运算符描述操作数个数表达式的值副作用
&&逻辑与20 或 1
逻辑或20 或 1
!逻辑非10 或 1

逻辑与&&

  • 如果两个操作数都为真(非零),那么表达式的值为真,否则为假。
  • 如果第一个操作数为真,第二个操作数没有计算的必要了,这种现象称为短路现象。
#include <stdio.h>

int main()
{
    double score = 70;

    if (score >= 70 || score <= 80)
    {
        printf("ok1 \n");
    }
    else
    {
        printf("ok2 \n");
    }

    int a = 10, b = 99;

    // 短路现象
    if (a > 5 || b++ > 100)
    { //
        printf("ok100 \n");
    }
    printf("b=%d\n", b);

    return 0;
}
输出结果:
ok1 
ok100 
b=99

逻辑或||

  • 只要有一个操作数为真,表达式的值就为真;两个操作数都为假,表达式的值为假。
  • 如果第一个操作数为真,第二个操作数没有计算的必要了,这种现象称为短路现象。

逻辑非!

  • 操作数状态取反作为表达式的值。
#include <stdio.h>

int main()
{
    int score = 100;
    int res = score > 99;

    if (res)
    {
        printf("hello, tom \n");
    }
    if (!res)
    { 
        printf("hello,jack \n");
    }

    return 0;
}
输出结果:
hello, tom

赋值运算符

运算符描述操作数个数表达式的值副作用
=赋值2左边操作数的值
+相加赋值2左边操作数的值
-=相减赋值2左边操作数的值
*=相乘赋值2左边操作数的值
/=相除赋值2左边操作数的值
*%=取余赋值2左边操作数的值
<<=左移赋值2左边操作数的值
>>=右移赋值2左边操作数的值
&=按位与赋值2左边操作数的值
^=按位异或赋值2左边操作数的值
=按位或赋值2左边操作数的值
  • 赋值运算符的第一个操作数(左值)必须是变量的形式,第二个操作数可以是任何形式的表达式。
  • 赋值运算符的副作用针对第一个操作数。
  • 左移赋值,右移赋值,按位与赋值,按位异或赋值,按位或赋值;均需要换算成二进制计算。
  • 异或相同为0,不同为1
#include<stdio.h>
int main()
{
    int a=1;
    int b=2;
    int c1=2;
    int c2=2;
    int c3=2;
    int c4=2;
    int c5=2;
    c1<<=b;//左移赋值
    printf("%d\n",c1);
    c2>>=b;//右移赋值
    printf("%d\n",c2);
    c3&=a;//按位与赋值
    printf("%d\n",c3);
    c4^=b;//按位异或赋值
    printf("%d\n",c4);
    c5|=4;//按位或赋值
    printf("%d\n",c5);

}
结果
8
0
0
0
6

位运算符

运算符描述操作数个数副作用
&按位与2
按位或2
按位异或2
~按位取反2
<<按位左移2
>>按位右移2

按位与、按位或、按位异或

#include <stdio.h>

int main()
{
    int a = 17;
    int b = -12;

    printf("a&b=%d\n", a & b); // a&b=16
    printf("a|b=%d\n", a | b); // a|b=-11
    printf("a^b=%d\n", a ^ b); // a^b=-27

    return 0;
}
输出结果:
a&b=16
a|b=-11
a^b=-27

按位取反

  • 如果正数取反,正数+1,前边加个负号,负数取反,|负数|-1
#include <stdio.h>

int main()
{
    int a = 17;
    int b = -12;

    // 按位非
    printf("~a=%d\n", ~a); 
    printf("~b=%d\n", ~b); 

    return 0;
}
输出结果:
~a=-18
~b=11

按位左移、右移

#include <stdio.h>

int main()
{
    int a = 17;
    int b = -12;

    // 按位左移
    printf("a<<2=%d\n", a << 2); // a<<2=68
    printf("b<<2=%d\n", b << 2); // b<<2=-48

    // 按位右移
    printf("a>>3=%d\n", a >> 3); // a>>3=2
    printf("b>>3=%d\n", b >> 3); // b>>3=-2

    return 0;
}
输出结果:
a<<2=68
b<<2=-48
a>>3=2
b>>3=-2

三元运算符

  • 条件表达式?表达式1:表达式2
  • 如果条件表达式为非0(真),整个表达式的值是表达式1
  • 如果条件表达式为0(假),整个表达式的值是表达式2

运算符优先级

  • 运算符优先级不用刻意地去记忆,总体上:一元运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符。

分支控制语句

多向分支 else if

if (条件表达式1)
{
    执行代码块1;
}
else if (条件表达式2)
{
    执行代码块2;
}
... 
else
{
    执行代码块n;
}

多项分支 switch

switch (表达式)
{
    case 常量值1:
       语句块1;
        break;
    case 常量值2:
       语句块2;
        break;
   … case 常量值n:
        语句块n;
        break;
    default:
       语句块n + 1;
}
  • switch后面表达式的值必须是一个整型(char、short, int, long等)或枚举类型。
  • case后面的值必须是常量,而不能是变量
  • default是可选的,当没有匹配的case时,执行default
  • reak语句可以使程序跳出switch语句块,如果没有break,会执行下一个case 语句块,直到遇到break或者执行到switch结尾,这个现象称为穿透

switch 和 else if的比较

  • 如果判断条件是判等,而且符合整型、枚举类型,虽然两个语句都可以使用,建议使用swtich语句。
  • 如果判断条件是区间判断,大小判断等,使用else if。

循环控制语句

while循环

while (循环条件表达式)
{
    循环体语句;
}
  • 当循环条件表达式成立,就执行循环体语句,直到条件不成立停止循环
  • 为避免死循环,循环条件表达式不能永远成立,且随着循环次数增加,应该越来越趋向于不成立
不确定循环直到循环表达式不成立之前,不确定循环次数,不需要循环变量。
实现需求:输入6位数密码,直到密码匹配成功结束循环。
#include <stdio.h>
int main()
{
    // 记录正确密码
    int pwd1 = 123456;
    // 定义变量用于获取输入的密码
    int pwd2;

    // 循环
    while (pwd1 != pwd2)
    {
        printf("请输入6位数密码:");
        scanf("%d", &pwd2);
    }

    printf("密码正确,欢迎回家!");

    return 0;
}

do...while循环

do
{
    循环体语句;
} while (循环条件表达式);
  • do…while循环是先执行再判断,但只有第一次循环语句的执行没有经过判断,以后的每一次仍然先经过判断
  • while后面的分号不能省略
输入6位数密码,直到密码匹配成功结束循环。
#include <stdio.h>

int main()
{
    // 正确密码
    int pwd1 = 123456;
    // 定义变量用于获取输入的密码
    int pwd2;

    // 循环
    do
    {
        printf("请输入6位数密码:");
        scanf("%d", &pwd2);
    } while (pwd1 != pwd2);

    printf("密码正确,欢迎回家!");

    return 0;
}

while和do while 的差异

#include <stdio.h>

int main()
{
    // while 循环 一次也不会执行
    int n = 10;
    while (n > 10)
    {
        printf("%d \n", n);
        n++;
    }

    // do while 陷入死循环
    n = 10;
    do
    {
        printf("%d \n", n);
        n++;
    } while (n > 10);

    return 0;
}
#### for循环
for (循环变量初始化; 循环条件表达式; 循环变量变化)
{
    循环条语句;
}
  • 循环变量初化只执行一次,且循环开始前就执行
  • 循环条件表达式每次循环都执行,同while循环一样,每次先判断后执行循环体语句
  • 循环标记变量变化每次循环都执行,在大括号中循环体语句之后执行
#include <stdio.h>

int main()
{
    // 正确密码
    int pwd1 = 123456;
    // 定义变量用于获取输入的密码
    int pwd2;

    // 循环
    for (; pwd1 != pwd2;)
    {
        printf("请输入6位数密码:");
        scanf("%d", &pwd2);
    }

    printf("密码正确,欢迎回家!");

    return 0;
}
5)案例 – 特殊结构的for循环
#include <stdio.h>

int main()
{
    // 标准结构
    for (int i = 1; i < 10; i += 2)
    {
        printf("%d ", i);
    }
    printf("\n\n");

    // 循环变量写在外面
    int i = 1;
    for (; i < 10; i += 2)
    {
        printf("%d ", i);
        ;
    }
    printf("\n\n");

    // 循环变量写在外面 循环标记变量变化写在大括号中
    i = 1;
    for (; i < 10;)
    {
        printf("%d ", i);
        i += 2;
    }
    printf("\n\n");

    // 使用两个循环标记变量
    for (int x = 1, y = 1; x <= 15, y <= 10; x++, y++)
    {
        printf("%d %d \n", x, y);
    }
    printf("\n\n");

    // for 后面括号中什么都不写 死循环
    for (;;)
    {
        printf("死循环 \n");
    }

    return 0;
}

多重循环

分别打印出以下两种形式的九九乘法表。
(1)第一种形式

#include <stdio.h>

int main()
{
    for (int i = 1; i <= 9; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            printf("%d*%d=%d\t", j, i, i * j);
        }
        printf("\n");
    }

    return 0;
}
(2)第二种形式

#include <stdio.h>

int main()
{
    for (int i = 9; i >= 1; i--)
    {
        for (int j = 1; j <= i; j++)
        {
            printf("%d*%d=%d\t", j, i, i * j);
        }
        printf("\n");
    }

    return 0;
}
(3)第三种形式

#include <stdio.h>

int main()
{
    for (int i = 1; i <= 9; i++)
    {
        for (int j = 1; j <= 9 - i; j++)
        {
            printf("\t");
        }

        for (int j = 1; j <= i; j++)
        {
            printf("%d*%d=%d\t", j, i, i * j);
        }
        printf("\n");
    }

    return 0;
}
(4)第四种形式

#include <stdio.h>

int main()
{
    for (int i = 9; i >= 1; i--)
    {
        for (int j = 1; j <= 9 - i; j++)
        {
            printf("\t");
        }

        for (int j = 1; j <= i; j++)
        {
            printf("%d*%d=%d\t", j, i, i * j);
        }
        printf("\n");
    }

    return 0;
}

跳转控制语句

break

  • break语句用于终止某个语句块的执行,用在switch语句或者循环语句中。
编写程序,要求输入一个数字,判断该数字是否是质数。
说明:质数指只能被1和自身整除且大于1的数字。
#include <stdio.h>
#include <stdbool.h>

int main()
{
    // 获取输入的数字
    int num;
    printf("输入一个数字:");
    scanf("%2d", &num);

    // 定义变量,标记是否为质数
    // 大于1的数字先标记为真,再通过循环看是否推翻; 小于1的数字直接标记为假
    _Bool isPrime = num > 1 ? 1 : 0;

    // 循环判断
    for (int i = 2; i <= num / 2; i++)
    {
        if (num % i == 0)
        {
            isPrime = 0;
            break;
        }
    }

    // 输出结果
    if (isPrime)
    {
        printf("%d 是质数!", num);
    }
    else
    {
        printf("%d 不是质数!", num);
    }

    return 0;
}

continue

  • continue语句用于结束本次循环,继续执行下一次循环。
输出100以内(包括100)的数字,跳过那些7的倍数或包含7的数字。
#include <stdio.h>

int main()
{
    for (int i = 1; i <= 100; i++)
    {   
        // i % 7 判断 7 的倍数
        // i % 10 判断个位上带7的数字
        // i / 10 判断十位上带7的数字
        if (i % 7 == 0 || i % 10 == 7 || i / 10 == 7)
        {
            continue; // 跳过
        }
        printf("%d\n", i);
    }

    return 0;
}

goto语句

  • goto语句是一种跳转语句,它允许程序控制流程在代码中跳转到带有标签(label)的语句处,标签(label)的名称可以自行设置,需要满足标识符规范。
  • 注意,我们在开发中不建议使用goto语句,但我们需要掌握 goto 语句的执行流程,以能够看懂其他开发者的代码中可能出现的 goto 语句。
goto 标签名  // 跳转到指定的标签(label)处
...
标签名:      // 定义一个标签(label)
语句;

goto 后面如果引用了没有定义的标签,编译器会报错!

使用 goto 语句实现语句跳转。
#include <stdio.h>

int main()
{
    printf("start \n");
    goto lable1; // lable1是标签名

    printf("ok1 \n");
    printf("ok2 \n");
lable1:
    printf("ok3 \n");
    printf("ok4 \n");

    return 0;
}
输出结果:
start 
ok3
ok4