先写一串代码:

#define _CRT_SECURE_NO_WARNINGS 1
int main()
{while (1){int c = getchar();if ('#' == c){break;}putchar(c);}return 0;
}

我们对putchar进行解释:把一个字符显示到我们到标准输出,也就是显示器上

这段代码有什么用呢?

答:可以检验我们输入到键盘上或者显示器上的内容是否都是字符,比如我们输入1234,假如我们输入的不是字符的话,if语句首先不满足条件,执行putchar函数,因为putchar函数能够把一个字符显示到我们的显示器上,假如我们输入到键盘上的内容并不是字符是,putchar函数是无显示的,所以证明了我们输入到键盘上或者显示器上的内容全部都是字符

我们对代码进行优化

#define _CRT_SECURE_NO_WARNINGS 1
int main()
{while (1){int c = getchar();if ('#' == c){break;}putchar(c);}printf("\nbreak out\n");return 0;
}

我们进行编译

由此看见,使用break时,我们会跳出整个循环。

当我们使用continue时

#define _CRT_SECURE_NO_WARNINGS 1
int main()
{while (1){int c = getchar();if ('#' == c){continue;}putchar(c);}printf("\nbreak out\n");return 0;
}

我们进行运行

由此可以知道continue的意思:continue的意思是跳过本次循环,也就是跳过一次循环

注意:continue跳过本次循环后,再次来到循环的判断位置,在这里就是到while循环的判定处

这里,我们出现一个问题:是不是对于所有的循环,continue都会再次来到循环的判断?

我们进行来举几个例子:

首先是do while循环

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

在do while循环内部的if循环中,看见continue,continue过后,程序又从哪里开始运行呢

答:到循环的判断条件处,也就是while(cond)

接下来就是for循环

int main()
{int i = 0;for (i = 0; i < 10; i++){printf("hello world\n");if (flag){continue;}}return 0;
}

对于for循环,continue的意思是跳过本次循环,然后跳转到for循环的条件更新出,也就是i++。

我们再举一个continue的例子

#include<Windows.h>
int main()
{int i = 0;for (i = 0; i < 10; i++){printf("continue before :%d\n", i);if (i == 5){printf("continue\n");continue;}printf("continue after:%d\n", i);Sleep(500);}return 0;
}

还是之前提到的问题:continue之后代码运行到什么位置?

答:这里需要假设,有三种情况,第一种情况运行到for循环内部的第一个printf

我们对这种情况进行解释:因为我们没有经过for循环,而i始终等于5,所以我们死循环打印continue并执行continue

第二种情况:continue之后代码运行到条件判断处,也就是i<10处

我们对这种情况进行解释:因为我们的i始终=5<10,所以我们始终执行if语句内部的内容,所以也是死循环

第三种情况:continue之后代码运行到条件更新处

我们对这种情况进行解释:我们continue之后,代码运行到i++处,所以i进行条件更新后,变成6,再进行条件判定,所以可以执行完毕整个for循环,我们进行编译看一下代码

代码并不是死循环,所以对于for循环内部的continue,跳过本次循环后,跳转到for循环的条件更新处

总结:continue对于不同的循环语句,跳过循环后跳转到不同的位置:对于while循环和do while循环语句,continue跳过循环后跳到while循环的条件判定处,对于for循环,continue跳过循环后跳到for循环的条件更新处。

在多层循环中,最长的循环放在最外层,最短的循环放在最内层,以减少cpu跨切循环次数

两个理由,第一个:cpu在存储数据的过程中,会不断缓存数据,在我们两个不同位置的代码来回切换的过程中,我们的cpu也是从缓存到过期来回跳转,这就导致我们的cpu在存储数据的过程中花费了太长的时间

第二个理由:局部性原理,意思就是代码呈现很密集的情况下,代码的效率会大大提高,因为我们的程序在加载的过程中,默认会把一个代码附近的代码也会加载到系统当中的,所以代码越密集,代码的执行效率越高。

for循环语句尽量要写成前闭后开型区间

理由有两个

第一个:前闭后开型区间的循环次数简单直观,就是两个区间端点值相减,例如

for (i = 0; i <10; i++){

这个语句的循环此时就是10-0为10 ,假如我们写成前闭后闭型区间时,我们的循环次数就是两个区间的端点值+1,例如,

for (i = 0; i <=9; i++){

我们的循环次数就是9-0+1也就是10

第二个:下标计算更加方便,例如

for (i = 0; i <10; i++){

假如我们根据for循环的循环次数,创建一个数组,注意数组的首元素也就是arr[1]对应的是i=0,arr[10]对应的是i=9,把整个数组都包裹完全了

for循环内,注意不要有浮点型的数据

goto语句的介绍

我们举一个例子

int main()
{goto end;printf("hello 1\n");printf("hello 2\n");printf("hello 3\n");
end:printf("hello 4\n");printf("hello 5\n");printf("hello 6\n");return 0;
}

goto语句是这样,跳过goto end和标签end的代码,直接执行标签end以后的代码。

如图所示 ,上面的goto语句表示的是向下跳转,其实,goto语句是可以任意跳转的,接下来,我们实现一下往上跳转

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");return 0;
}

我们进行编译

代码出现死循环,原因是什么?

答:代码每次运行到goto语句都会跳转到end标签处,end打印后会继续到goto语句,所以死循环

接下来,我们举一个goto语句应用的例子

int main()
{int i = 0;
start:printf("[%d] goto running \n", i);i++;if (i < 10){goto start;}printf("goto end\n");return 0;
}

我们进行运行

goto语句可不可以跨代码块使用

答:不能,我们进行检测

void fun()
{
start:printf("enter fun()");
}
int main()
{int i = 0;printf("[%d] goto running \n", i);i++;if (i < 10){goto start;}printf("goto end\n");return 0;
}

我们把goto语句的标签start放在我们自定义的函数fun()里面,我们进行编译,如果goto语句可以跨代码使用,应该会打印出enter fun()

可以发现,生成错误,所以:goto语句是不能跨代码块使用

很多公司禁止使用goto语句,不过这个问题我们还是灵活看待,goto在解决很多问题时有奇效的

下面提出一个问题:是否可用void来定义变量

我们写一个代码进行检测

int main()
{void x = 0;
}

我们进行编译

所以是不能用void类型来定义变量的,那么原因是什么呢?

有人会说:因为void类型是空类型,定义变量时开辟的空间是未知的,所以不能用来定义变量。

这种说法是可以理解的,但是真正的原因是什么呢?

我们先写一个代码

int main()
{printf("%d", sizeof(void));return 0;
}

我们这里求的就是void类型的变量占据空间的大小,我们进行编译

我们可以发现,结果为0,我们再在Linux系统上尝试一下 

我们发现,在linux系统中void类型的变量却占据1个字节,所以void类型的变量开辟的空间不一定都是0,所以上面的说法不成立。真正正确的说法在下面总结处

总结:void本身就被编译器解释为空类型,强制的不允许定义变量

我们来写一个代码

void test()
{printf("hello test\n");return 1;
}
int main()
{test();
}

我们的编译器是能编译过去的

但是只要我们创建了一个变量来接受这个函数的返回值

void test()
{printf("hello test\n");return 1;
}
int main()
{int a=test();
}

我们进行编译,可以发现

代码报错,所以我们得出结论void类型的函数,正常情况下是能编译过去的,但是假如我们创建了一个变量来接受这个函数,就会报错。

我们把函数的返回值类型void去掉,可以发现

test()
{printf("hello test\n");}
int main()
{test();
}
test()
{printf("hello test\n");}
int main()
{int a= test();
}

无论是否创建变量接受函数的返回值,函数都不会报错

所以在c语言中,可以不带返回值,默认的返回值类型是int

那是不是就说明了以后我们在书写函数的时候,是不是可以不带返回值类型呢?

答:不可以,如果我们的函数没有返回值时,我们还是要在返回值的前面加上void类型

因为:在默认的情况下,函数的返回值是整型,在没有返回值的时候,返回值的类型也是整型,所以当别人看见你的代码,别人就会产生疑问:是这个忘写返回值了,还是这个函数是没有返回值的。

void修饰函数返回值有两个作用

1:一方面告诉代码的编写者不要添加返回值了

2:当你加上void类型,即使你有返回值,如果你不接受的情况下,编译是能编过的,但是只要你想要接受,或者存储返回值,编译就无法通过,起到检验错误的作用

我们再写一串代码

int test1()
{return 1;
}
int test2(void)
{return 1;
}
int main()
{test1(1, 2, 3, 4);
}

我们对代码进行分析:首先,第一个函数test1和第二个函数test2的区别在于test2函数没有参数的

我们对test1传参,进行编译,可以发现,代码正常运行

但是当我们把对test2函数传参时,在编译器vs2013版本下,依旧正常运行,但是代码产生警告

总结:void充当函数的形参列表,告诉编译器和代码的编写者函数不需要传参

void不能用来创建变量,那么void*可以吗?

答:可以,原因如下:因为类型明确,void*就是一个指针,在32维平台下占四个字节,64位平台下占八个字节

写一串代码

int main()
{void*p = NULL;double*x = NULL;int *y = NULL;x = p;y = p;
}

我们进行编译,可以发现代码正确运行

总结:void型的指针可以用其他任何类型的指针来接受

我们再换一种写法

int main()
{void*p = NULL;double*x = NULL;int *y = NULL;x = p;y = p;p = x;p = y;
}

我们进行运行,依旧成功运行

总结:void型的指针可以接受任意类型的指针

提问:void类型的指针可以进行加减运算吗?

我们写一个代码进行检验

int main()
{int *p = NULL;p++;p--;
}

我们首先写一个整型指针,检验其是否可以进行加减运算

代码是可以运行的 ,接下来我们试试void类型的指针

int main()
{void *p = NULL;p++;p--;
}

可以发现

产生错误,所以void型的指针是不能进行加减运算的

究其原因是:指针加减通常是从一个指针变量移位到另一个指针变量,所以涉及到指针类型的步长,因为void类型是没有步长的,也就不清楚加1减1移位的距离,所以不能进行加减运算

注意:在Linux系统中,void类型的指针是可以加减运算的,原因是因为在linux中,void类型的步长被认为是1

void类型的指针能够直接解引用吗?

答:不能

int main()
{void*p = NULL;*p;
}

我们进行编译:

有人可能会认为p为空指针,所以不能解引用,所以我们换一个其他的

int main()
{int a = 10;void*p = &a;*p;
}

注意:我们之前有说过,void型的指针能够接受任意类型的指针变量,所以也能接受int类型的指针。我们进行运行

依旧是非法寻址。

总结:void类型的指针不能直接解引用

为什么呢?

答:因为p的类型void类型,void类型的指针解引用后也是void类型的变量,因为void类型的变量是无法创建的,所以void型的指针不能直接解引用

注意:c语言中有字符串,但是没有字符串类型。

第8讲 - C语言关键字(8)相关推荐

  1. c语言 char转int_C语言关键字及进制的转换你都知道吗?

    ​前面我们讲过 C语言简洁.紧凑 使用方便.灵活 那是什么使得C语言这么方便呢? 那就是关键字,或称保留字 C语言的关键字共有32个 根据关键字的作用 可分为 数据类型关键字 控制语句关键字 存储类型 ...

  2. c语言关键字不做标识符,C语言标识符、关键字、注释、表达式和语句

    这一节主要讲解C语言中的几个基本概念. 标识符 定义变量时,我们使用了诸如 a.abc.mn123 这样的名字,它们都是标识符(Identifier). 标识符就是程序员自己起的名字,除了变量名,后面 ...

  3. 计算机java语言教程,计算机JAVA教程二讲Java语言基础知识.doc

    计算机JAVA教程二讲Java语言基础知识 2.1简单数据类型 2.1.1 标识符和保留字 1.标识符 程序员对程序中的各个元素加以命名时使用的命名记号称为标识符(identifier).Java语言 ...

  4. C语言关键字----Const

    C中CONST的使用: 虽然这听起来很简单,但实际上,const的使用也是c语言中一个比较微妙的地方,微妙在何处呢?请看下面几个问题. 问题:const变量 & 常量 为什么下面的例子在使用一 ...

  5. 【译】volatile C语言关键字,如何使用?

    原文 概要 许多程序员无法正确的理解C语言关键字volatile.这并不奇怪,大多数C原因书籍不过一两句一带而过.本文将告诉你如何正确使用它. 在C/C++嵌入式代码中,你是否经历过下面的情况: 代码 ...

  6. c语言 关键字 and,C语言的关键字(一)

    每次讲关键字之前,我总是问学生:C 语言有多少个关键字?sizeof 怎么用?它是函数 吗?有些学生不知道 C 语言有多少个关键字,大多数学生往往告诉我 sizeof 是函数,因为 它后面跟着一对括号 ...

  7. 从关键字~C语言 — 期末考,考研,面试中那些你不得不知道的C语言关键字细节

    目录 引言: 初步认识了C语言的结构之后 博主将带您进入关键字的世界了 1. 关于变量 1.1 什么是变量 1.2 变量的定义与声明 1.3 为什么要定义变量 1.4 变量定义的本质 2. 关键字 2 ...

  8. 第3讲 C语言之函数讲解 Function

    第3讲 C语言之函数讲解 Function 1. C语言函数的定义与声明(define & declare) 1.1 C语言的入口函数Main函数 1.2 C语言的自定义函数 1.2.1 C语 ...

  9. c语言入门第1讲,第1讲-c语言入门.ppt

    第1讲-c语言入门.ppt * * * * * * * * * * * * * * * * * * * * * * * * * * * 母板制作:J0座机电话号码 张茂国 母板制作:J0座机电话号码 ...

最新文章

  1. HTML教程--多页面窗体
  2. Linux gdb 破解软件密码
  3. 数据库面试题【十五、优化查询过程中的数据访问】
  4. [转帖]Linux修改时区
  5. C++中 引用与取地址的区别
  6. 爬虫 spider08——爬取腾讯娱乐新闻【使用redis去重】
  7. 简述使用REST API 的最佳实践
  8. 淘宝设计万能PSD分层模板(简约页面设计——少即是多)
  9. 《统计学习方法》(李航)读书笔记
  10. 【备注】【C14】《HeadFirstJava(中文版)(第2版)》 PDF 下载
  11. 初次联系导师短信模板_申博经验分享|如何联系导师?
  12. Mark down学习日记
  13. 计算机应用唐家琪,基于机器学习的蛋白质相互作用预测研究
  14. 爬取雪球网的股票信息评论
  15. A - Robot Rapping Results Report
  16. 智商情商哪个重要_情商与智商哪个更重要?三个方面让你彻底明白
  17. 了解黑客经常使用哪些工具
  18. 英语句子主干成分分析
  19. [VCS]Coverage Options Introduction
  20. [原][彩]情诗两首[下]--期对酒于襄阳,待重归于长江。

热门文章

  1. ImportError: /home/yang/anaconda3/envs/sar/bin/../lib/libgio-2.0.so.0: undefined symbol: g_unix_get_
  2. CRMEB商城直播功能-微信小程序直播
  3. SQL Server性能优化
  4. 第1关 Numpy创建数组 (educoder
  5. android下开启AP热点
  6. 微信装修装饰小程序源码开发方案
  7. Windows指纹登录
  8. 原始套接(ARP协议的使用)
  9. Java中的statis用法
  10. Matplotlib——饼图pie()函数