C深剖关键字(2)

简介: 目录一:signed / unsigned关键字二:switch关键字三:break / continue关键字四:goto关键字

一:signed / unsigned关键字

image.png

在正式了解signed / unsigned关键字之前,我们需要对数据在所开辟内存中到底是如何存储进行一个深入了解。 首先就要了解:


整数的二进制表示有3种表示形式:原码----反码----补码


而内存存储的是二进制的补码!

整数:正数 / 负数

正数:原码反码补码相同

负数:原码:按照一个数的正,负直接写出来的二进制就是原码

           反码:符号位不变,其他位按位取反

           补码:反码的二进制序列+1,就是补码

符号位为0,正数,为1,负数

15:

00000000000000000000000000001111   ----->原码-反码-补码    最高位为符号位0,正数

-15:

//10000000000000000000000000001111   ----->原码

//11111111111111111111111111110000   ----->反码

//11111111111111111111111111110001   ----->补码


10

00000000000000000000000000001010  原码反码补码相同

4个二进制转化为一个16进制

0   0   0   0   0   0   0   1

-10

10000000000000000000000000001010  原码

11111111111111111111111111110101  反码

11111111111111111111111111110110  补码

4个二进制转化为一个16进制

f   f   f   f   f   f   f    6


为什么内存存储的是二进制的补码呢

计算机只有加法器

如 1+(-1)=0

若采用原码相加:

00000000000000000000000000000001   1的原码

10000000000000000000000000000001   -1的原码

---------------------------------  相加

10000000000000000000000000000010 ----> -2 err

若采用补码相加:

00000000000000000000000000000001   1的补码

11111111111111111111111111111111   -1的补码

---------------------------------  相加

100000000000000000000000000000000 ----> 0 right

原码到补码,补码到补码:

 1

法一:

10000000000000000000000000000001  原码

               取反

11111111111111111111111111111110  反码

               加1

11111111111111111111111111111111  补码

               减1

11111111111111111111111111111110  反码

               取反

10000000000000000000000000000001  原码

法二:

10000000000000000000000000000001  原码

               取反

11111111111111111111111111111110  反码

               加1

11111111111111111111111111111111  补码

               取反

10000000000000000000000000000000  

               加1

10000000000000000000000000000001  原码

综上所述:

原码取反+1得到补码,补码再取反+1得到原码


正如我们实际定义一个无符号数如下:

#include<stdio.h>
int main()
{
  unsigned int b = -10;
  printf("%d\n", b); // -10
  printf("%u\n", b); // 4294967286
  return 0;
}

解析:


我们在此代码中定义了一个无符号数b=-10的变量,


数据要先存再取,存补码,取原码。


我们都清楚内存存储的是补码


-10

10000000000000000000000000001010  原码

11111111111111111111111111110101  反码

11111111111111111111111111110110  补码


当用%d的形式输出时,此时就将其看成是一个有符号数,将上述补码转换为原码即为-10


当用%u的形式输出时,才是正儿八经的无符号数,而无符号数的最高位就不再是符号位,此时原码反码补码相同,将上述二进制补码转换为十进制就是一个超大的数字4294967286


二:switch关键字

基本语法结构:

switch (整型变量 / 常量 / 整型表达式) 
{
case var1:
  break;
case var2:
  break;
case var3:
  break;
default:
  break;
}

注意:

// // 任何具有判定能力的语法结构,都必须具备:判定+分支

// //case本身是用来判定的

// //break用来进行分支功能

#include<stdio.h>
int main()
{
  int day = 0;
    while (1)
  {
      scanf("%d", &day);
    switch (day)  // 整型||整形表达式||常量
    {
    case 1:  // case本身是用来判定的
      printf("星期1\n");
      break; //break用来进行分支功能
    case 2:
      printf("星期2\n");
      break;
    default:
      printf("请输入正确的数字\n");
      break;
    }
  }

若要一个case执行多条语句:

可以在其中一条case语句后多输出相关语句

    case 3:
      printf("星期3\n");
      printf("星期3\n");
      printf("星期3\n");
      printf("星期3\n");
      printf("星期3\n");
      break;

但是,如果我们在case后定义一个变量并且需要访问它时,如下:


image.png


不难发现,编译器出错 ,但是当我们在整个case3后面加一个花括号呢


image.png


此时编译器是可以正常运行的 ,当然,想要执行上述操作,我们最建议的还是创造函数来解决:


image.png


如果想要多条case执行一条语句时:

#include<stdio.h>
int main()
{
  int day = 0;
  while (1)
  {
    scanf("%d", &day);
    switch (day)  // 整型||整形表达式
    {
    case 1:  
    case 2:
    case 3:
    case 4:
    case 5:
      printf("周内\n");
      break;
    case 6:
    case 7:
      printf("周末\n");
      break;
    default:
      printf("请输入正确的数字\n");
      break;
    }
  }
  return 0;
}

image.png

注意:case 后面不能直接跟变量,但可以用宏定义变量即为常变量,default语句的位置可以放在任意位置。

#include<stdio.h>
#define A 10
int main()
{
  const int a = 10;
  switch (a)
  {
  //case 10:
  //case a: err
  //case 后面不能直接跟变量,但可以用宏定义变量即为常变量
  case A:
    printf("hello bit!\n");
    break;
  default :
    break;
  }
  return 0;
}

总结:


1.switch语法结构中,case完成的判定功能,break完成的分支功能,default处理异常情况


2.case:执行语句==1:n,case多条语句(不能定义变量,如果需要,{},函数) break


3.case:执行语句= =n:1,多条case后续不写break


4.default:可以出现在任何地方,推荐放在结尾


5.case:不能:const,普通的变量,建议要有好的布局case的方式


三:break / continue关键字

while


先看一段代码(break)


image.png


我们不难发现break的作用就是跳出循环,当把break换成continue时


image.png


continue的作用就是结束本次(一次)循环,既然是结束本次循环,所以此时continue跳到while条件判定那进行循环


do while


先看一段伪代码

  do {
    printf("hello\n");
    if (flag)
    {
      continue;
    }
  } while (cond);

在do while中,使用continue,continue会跳到哪呢?


条件判断在哪里,continue就跳转到哪里,所以continue跳转到while(cond)条件判断那


for


再看一段伪代码


image.png


在for循环中,使用continue,continue会跳到哪呢?


此时我们不难发现 ,for循环的continue会跳转到条件更新处i++处


总结:


while循环 do while循环用continue都是到条件判定处


for 循环是到条件更新处


四:goto关键字

看代码:


向下跳转:

#include<stdio.h>
int main()
{
  goto end;
  printf("hello 1\n");
  printf("hello 2\n");
  printf("hello 3\n");
  end: // 标签
  printf("hello 4\n");  // hello 4
  printf("hello 5\n");  // hello 5
  printf("hello 6\n");  // hello 6
  return 0;
}

向上跳转:

#include<stdio.h>
int main()
{
    end: // 标签
  printf("hello 1\n");
  printf("hello 2\n");
  printf("hello 3\n");
  goto end;  
  printf("hello 4\n");  
  printf("hello 5\n");  
  printf("hello 6\n"); 
  // 死循环
  // goto语句在代码块中可以跳转
  return 0;
}

案例:

#include<stdio.h>
int main()
{
  int i = 0;
start:
  printf("[%d] goto running...\n", i);
  i++;
  if (i < 3)
  {
    goto start;
  }
  printf("goto end...\n");
  return 0;
}

image.pnggoto语句只能在本代码块内使用,不能跨文件和使用函数访问!!!

总结:

//很多公司确实禁止使用goto,不过,这个问题我们还是灵活对待,goto在解决很多问题是有奇效的。

//我们可以认为goto使用场景较少,一般不使用。但是必须得知道goto,需要的时候,也必须会用

相关文章
|
3月前
|
Java 程序员 开发者
深入解读:synchronized关键字背后的“黑科技”!
深入解读:synchronized关键字背后的“黑科技”!
29 4
|
6月前
|
Java 编译器
Java编程语言中,关键字和标识符
Java编程语言中,关键字和标识符
48 1
|
Java
关于关键字volatile的一二
关于关键字volatile的一二
73 0
|
JavaScript 前端开发
|
JavaScript 前端开发
|
JavaScript 前端开发
|
存储 算法 编译器
深剖关键字(跑路人笔记2)
深剖关键字(跑路人笔记)
深剖关键字(跑路人笔记2)
|
存储 编译器 Linux
C深剖关键字(4)
目录 一:volatile关键字 二:extern关键字 三:struct关键字
C深剖关键字(4)
|
存储 编译器
C深剖关键字(5)
目录 一:union关键字 二:enum关键字 三:typedef关键字
C深剖关键字(5)
|
存储 安全 编译器
C深剖关键字(1)
目录 一:auto 1.1 局部变量与全局变量 1.2 auto相关 二:register 三: static 四:sizeof
C深剖关键字(1)