c生万物---第一章 初识c语言

  • 前言
  • 1、什么是C语言
  • 2、第一个C语言程序
  • 3、数据类型
  • 4、变量、常量
    • 4.1定义变量的方法
    • 4.2变量的分类
    • 4.3变量的使用
    • 4.4 变量的作用域和生命周期
    • 4.5常量
  • 5、字符串+转义字符+注释
    • 5.1字符串
    • 5.2 转义字符
    • 5.3注释
  • 6、选择语句
  • 7、循环语句
  • 8、函数
  • 9、数组
    • 9.1数组定义
    • 9.2 数组的下标
    • 9.3 数组的使用
  • 10、操作符
  • 11、常见关键字
    • 11.1 关键字 typedef
    • 11.2 关键字static
    • 11.2.1 修饰局部变量
    • 11.2.2 修饰全局变量
    • 11.2.3 修饰函数
  • 12、define 定义常量和宏
  • 13、指针
    • 13.1 内存
    • 13.2 指针变量的大小
  • 14、结构体

前言


小编让大家利用本篇内容,对c语言有个全貌的认识都感知一下,然后接下来才是细致的学习,后面的阶段才是细枝末节,希望大家明白小编的设计思路。

1、什么是C语言


 C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
(在应用层下面的东西就是底层,所以c语言特别擅长写操作系统和驱动)

 尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。
 二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。 目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。

个人解释:
计算机语言实际就是二进制语言,由0和1组成。
例如:100100111
 用二进制语言很难操控计算机,这样下去的话计算机是普及不了的,后来就有了汇编语言。比如:ADD 就是这么一个二进制序列100110,而给二进制序列起名字这种符号叫助记符,帮助你记忆的。这就是汇编语言。
 再后来发展出我们的B语言。
 最后发展出我们的C语言,c语言在早期当然是有些不足的地方,各大厂商为其改进c语言它们就各不相同了,比如我写的代码在你的编译器上跑不过去,你写的也在我的编译器上执行不了,这时候就出现了国际标准规定c语言是什么样子的,如果一门语言有国际标准的话说明这种语言发展的很不错。

 C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。
 其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。

个人解释:
我们现在用到的微软的编译器就是MSVC
小编用到的是VS2013/VS2019叫做集成开发环境,集成了MSVC这样的编译器,所以我们的VS2013和VS2019可以编写编译我们的c语言代码。

2、第一个C语言程序


个人解释:
下面我们来看一下如何在VS2013中创建项目如何去执行第一个简单的c语言程序吧(VS2013和VS2019的功能几乎一样这里拿VS2013来做示范)
1、安装好VS2013打开之后选择“新建项目“我们继续点击“visual C++”,再点击“空项目”,把项目的名称和路径自己写好,最后点击确定。(新建项目)

正常情况下你如果看见“解决方案资源管理器“那么说明你的项目创建成功了

如果你不小心把“解决方案资源管理器”关掉了,不要担心我们可以点击“视图”来显示窗口找出我们的项目。

2、第二步新建源文件,那什么是源文件呢,在c语言当中以.c为后缀的文件称为源文件,(以.h结尾的文件称为头文件),点击“源文件”点击“添加”点击“新建项”。

点击“visual C++”点击“C++文件”,然后一定要把名称改为以.c结尾的文件,最后点击添加。

那么这里我们的源文件就创建好了,可以直接写代码了

3、创建好源文件之后我们开始写代码,我们虽然没有吃过猪肉但是我们今天来看一下猪跑。

个人解释:为什么要写主函数呢,当你写了500行的代码,如何去执行呢,c语言是从主函数的第一行开始执行的,所以c语言代码中得有main函数(主函数),没有入口怎么执行啊对不对。大括号之间的叫做函数体{ },int叫做函数的返回类型(int为整型就是整数后边会讲到),main()叫做函数名注意小括号。return 0 就是返回0这样一个整型。这就是我们主函数的一个标准的写法,而未来我们我们在写代码的时候,大部分代码都会写到主函数里边去。
注意:一个工程里可以有多个.c文件,但是多个.c文件中只能有一个main函数


接下来我们来写一个简单的可以运行的代码。

个人解释:我们来写个代码,在屏幕上打印:哈哈,怎么打印呢,我么有一个函数叫printf()打印函数,printf 是库函数作用是在屏幕上打印信息的,但是使用库函数的东西那是别人的东西,你也得打招呼意思就是引用头文件 stdio.h,因为关于这个函数的信息是放在头文件里边的,具体这样引用“#include <stdio.h>”,包含头文件的意思,大家这里会很多疑惑,我们先接触,后面会慢慢讲到

#include <stdio.h>int main()
{printf("哈哈\n");return 0;
}

4、最后一步编译加运行

个人解释:编译+链接+运行代码我们只需要按一个快捷键就可以了,Ctrl+F5就可以了,这时候我们会发现因为程序执行的太快,没有看到“哈哈”这两个字出现在屏幕上,为了看到结果,我们这里需要设置一下VS2013的属性。右击我们的“项目名称“,再点击“属性”

找到我们的“配置属性”点击“链接器”,点击“系统”,找到“子系统”,改为“控制台”就可以了。


这个时候我们再回到代码块按住快捷键,就会显示我们的“哈哈”了
快捷键:ctrl+f5 或者 fn+ctrl+f5

3、数据类型


个人解释:我们使用计算机语言是用来写程序的来解决生活中的问题,而计算机必须有能力来描述生活中的问题!比如你写一个购物商城系统,这时候你得商城得上架商品,那这个商品应该有价格吧,那你写出的程序必须有能力来描述价格,那么价格比如15.6元它是一个小数啊,所以c语言必须有来能力描述这些数字,而小数呢在c语言中叫做浮点数,在c语言当中假如要描述一个人的年龄为50就是整数叫做整型
这里肯定会有很多同学可能会疑惑,光是整型为什么就搞出四种呢?大家注意short类型的空间一定要比int类型的空间要小,short里只有16个比特位,而int里会有24个比特位,那如果我们存储的那个值不大,我们会选择short会更省空间一些,而选择int的话空间就会浪费更多一些,所以从这个角度来讲的话,我们的空间利用率就会更高,所以说为什么c语言当中这么多的数据类型。

类型 values 例如 大小(字节)
char 字符数据类型 ‘a’ 1
short 短整型 10 2
int 整型 20 4
long 长整型 100 4
long long 更长整型 1000 8
float 单精度浮点型 3.1 4
double 双精度浮点型 3.1415926 8

例如:

个人解释:我们要用代码把字符a存起来怎么存呢?先把主函数写出来。就好像我这里有一本书想把它放起来我得找一个书架子(空间)来放,书架上有格子我才能放,意思就是什么东西存储都需要一个空间,我这里有一些水想存起来是不得需要一个杯子,所以数据存起来都需要空间,这里我们拿char(字符类型)类型创建了个空间叫ch然后把字符a存到空间里去。其他类型也是同样的规则。

#include<stdio.h>
int main()
{//字符类型char ch = 'a';//整型int age = 20;//短整型short num = 10;//long //long long//单精度浮点型float weight = 55.5;//双精度浮点型double d = 0.0;
return 0;
}

个人解释:下面代码这中%d是将100这个数字以整型的形式去打印(%s是以字符串的形式打印,%c是以字符形式打印,%f是以浮点数类型打印)。sizeof是一个关键字,也是c语言当中的一个操作符,它是用来计算类型或者变量所占空间的大小的,单位是字节(byte)。

int main()
{//printf("hehe\n");//printf("哈哈\n");//printf("%d\n", 100);//打印一个整数 - %d//sizeof - 关键字 - 操作符 - 计算类型或者变量所占空间的大小printf("%d\n", sizeof(char));printf("%d\n", sizeof(short));printf("%d\n", sizeof(int));printf("%d\n", sizeof(long));printf("%d\n", sizeof(long long));printf("%d\n", sizeof(float));printf("%d\n", sizeof(double));return 0;
}

说到字节我们来了解一下计算机中的单位:
1B(Byte 字节)=8bit,
1KB (Kilobyte 千字节)=1024B,
1MB (Megabyte 兆字节 简称“兆”)=1024KB,
1GB (Gigabyte 吉字节 又称“千兆”)=1024MB,
1TB (Trillionbyte 万亿字节 太字节)=1024GB,其中1024=2^10 ( 2 的10次方),
1PB(Petabyte 千万亿字节 拍字节)=1024TB,
1EB(Exabyte 百亿亿字节 艾字节)=1024PB,
1ZB (Zettabyte 十万亿亿字节 泽字节)= 1024 EB,
1YB (Yottabyte 一亿亿亿字节 尧字节)= 1024 ZB,
1BB (Brontobyte 一千亿亿亿字节)= 1024 YB.

4、变量、常量


个人解释:其实拿这么多数据类型是来创建变量的。生活中有一些数据,而这些数据是有特点的,有些数据是可变的,比如工资、年龄、体重等。而有些数据是不可变的,比如血型、性别、圆周率等。那当我们用c语言如何描述,c语言中有个概念叫常量,它是描述那些不能改变的量,而变量就自然描述的是能被改变的量。

4.1定义变量的方法

个人解释:这里创建一个变量它的类型是int,age是变量的名字,如果你愿意的话你可以给它赋一个初值

#include<stdio.h>
int main()
{int age = 20;double weight = 75.3;age = age+1;            //变量意味着可以更改,所以给age加1weight = weight - 10;printf("%d\n", age);printf("%lf\n", weight);  //%lf是打印双精度浮点型return 0;
}

4.2变量的分类

  • 局部变量
  • 全局变量

个人解释:在大括号{}内部定义的变量叫做局部变量,在大括号{}外部定义的变量叫全局变量,当局部变量和全局变量名字冲突的情况下,局部优先,我们不建议把全局变量和局部变量的名字写成一样的。最终打印的结果为10

#include<stdio.h>
int a = 100;  //全局变量+int main()
{int a = 10;    //局部变量printf("%d\n", a);return 0;
}

4.3变量的使用

写一个代码求2个整数的和

个人解释:scanf函数是输入函数,两个%d的意思是输入两个整型,输入的数据分别放到a和b,最后把a+b的结果放到sum中。\n是换行符。当你去执行的时候就会报错,因为scanf_s是vs提供的不是c语言标准规定的,所以我们不建议使用scanf_s我们是用scanf函数来替代它,我们只需要加入这一条"#define _CRT_SECURE_NO_WARNINGS 1"就可以了,一定要在文件最开始处添加。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{int a = 0;int b = 0;int sum = 0;scanf("%d %d", &a, &b);sum = a + b;printf("sum = %d\n", sum);return 0;
}

4.4 变量的作用域和生命周期

作用域

作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的而限定这个名字的可用性的代码范围就是这个名字的作用域。

  1. 局部变量的作用域是变量所在的局部范围。
  2. 全局变量的作用域是整个工程。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>int g_val = 2021;//全局变量int main()
{printf("1:%d\n", g_val);printf("hehe\n");{printf("2:%d\n", g_val);int a = 10;           //这个a所在的作用域就是所在的大括号之内{},出了大括号就不能用printf("a = %d\n", a);}printf("3:%d\n", g_val);return 0;
}

调用本工程内其它.c文件中的全局变量

个人解释:在同一工程内我们跨文件了,直接用肯定是不行的,我们必须得声明变量才可以使用。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>extern int g_val;int main()
{printf("%d\n", g_val);return 0;
}

生命周期

变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段

  1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
  2. 全局变量的生命周期是:整个程序的生命周期。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>int main()
{{                     //变量a的声明周期开始int a = 10;      printf("%d\n", a);  //变量a的声明周期结束}return 0;
}

4.5常量

C语言中的常量和变量的定义的形式有所差异。
C语言中的常量分为以下以下几种:

  • 字面常量
  • const 修饰的常变量
  • define 定义的标识符常量
  • 枚举常量

1、字面常量

int main()
{3.14;   //浮点型常量10;     //整型常量'a';    //字符常量"abcdef";    //字符串常量return 0;
}

2、const 修饰的常变量

个人解释:如果这个变量被const修饰,那么就变成常量(不能改变值),所以叫常变量,但是本质上它是变量

int main()
{const int num = 10;//num就是常变量 - 具有常属性(不能被改变的属性)num = 20;printf("num = %d\n", num);//20return 0;
}

个人解释:下面我们来证明一下常变量本质是变量,当const修饰n时代码还是无法执行,因为n还是一个变量(常变量),

int main()
{int arr[10] = {0};//10个元素const int n = 10;int arr2[n] = {0};//n是变量的,这里是不行return 0;
}

没有加const时n是个变量,无法执行

加了const修饰之后本质还是变量,无法执行

3、#define 定义的标识符常量

#define MAX 10000
int main()
{MAX = 20000;//err,错误,常量是不能改变的int n = MAX;printf("n = %d\n", n);return 0;
}

4、枚举常量

个人解释:枚举常量用于可以一一列举的常量,比如性别(男,女,保密),血型(O,A,B),星期(1~7)

性别
enum Sex
{//这种枚举类型的变量的未来可能取值//枚举常量MALE = 3,//赋初值,不是改变它的值,是最开始就有个值,那它的值默认是从3开始的那么female和secret的值分别为4,5FEMALE,SECRET
};int main()
{//4. 枚举常量//可以一一列举的常量enum Sex s = MALE;//MALE = 3;//err,不能改printf("%d\n", MALE);printf("%d\n", FEMALE);printf("%d\n", SECRET);return 0;
}

枚举常量它的值默认是从0开始的

5、字符串+转义字符+注释


5.1字符串

“hello bit.\n”
这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。

int main()
{"abcdef";"hello";return 0;
}

个人解释:字符串是一串字符,那多个字符我们要存起来应该怎么存呢,这里就用到了字符数组的概念,数组是一组相同类型的元素,那我们可以把hello这个字符串存到字符数组里

int main()
{//字符串在结尾的位置隐藏了一个\0的字符//\0是字符串的结束标志char arr[] = "hello";return 0;
}

个人解释:我们经过调试发现里面有6个字符,其实在字符串的末尾隐藏了一个字符\0


这里我们来证明一下

int mian()
{char arr1[] = "abc";char arr2[] = {'a', 'b', 'c'};printf("%s\n", arr1);printf("%s\n", arr2);return 0;
}

个人解释:arr1里边有四个字符,arr2里边有三个字符

个人解释:最终打印的效果,发现两种不一样,第一种打印完abc停下来了,因为遇到了\0结束标志,就不在打印了。第二种打印完abc没有遇到\0结束标志就继续打印后面的内容。

最终加上\0,abc就打印出来了,这里充分证明\0是字符串的结束标志

个人解释:strlen是求字符串长度的,第二个为什么是15呢,因为是随机值。

#include <string.h>         //strlen头文件int main()
{char arr1[] = "abc";char arr2[] = {'a', 'b', 'c'};//求一下字符串的长度printf("%d\n", strlen(arr1));printf("%d\n", strlen(arr2));return 0;
}

5.2 转义字符

假如我们要在屏幕上打印一个目录: c:\code\test.c
我们该如何写代码?

个人解释:我们发现直接打印并没有\t,这个地方就是转义字符捣的鬼,这里不在是\tt它转变了原来的意思,所以叫转义字符(转变了它原来的意思)

int main()
{printf("c:\test\test.c");    return 0;
}

实际运行结果是这样的

这里就不得不提一下转义字符了。转义字符顾名思义就是转变意思。
下面看一些转义字符。

转义字符 释义
\? 在书写连续多个问号时使用,防止他们被解析成三字母词
\’ 用于表示字符常量’
\“ 用于表示一个字符串内部的双引号
\\ 用于表示一个反斜杠,防止它被解释为一个转义序列符。
\a 警告字符,蜂鸣
\b 退格符
\f 进纸符
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ddd ddd表示1~3个八进制的数字。 如: \130 X
\xdd dd表示2个十六进制数字。 如: \x30 0
  • 示例

个人解释:我们c语言会把“ ??) “解析成一个“ ] ”,这就叫三字母词
假如我我们就想输出" ??) “呢?这时我们在两个?前加“ \ ”转义一下就会输出” ??) "了。
小编给大家解释几个难理解的,剩余的大家可以自己测试一下。

int main()
{printf("(are you ok??)");        //   ??) -- ] - 三字母词printf("(are you ok\?\?)");              printf("%c\n", '\'');           //在屏幕上打印一个单引号,加\转义printf("%s\n", "\"");           //在屏幕上打印一个双引号,加\转义printf("%s\n", "'");            //打印单引号的第二种写法printf("c:\\test\\test.c");     //打印c:\code\test.cprintf("\a");                    //蜂鸣//printf在打印数据的时候,可以指定打印的格式 %s是打印字符串的return 0;
}

个人解释:这里特别解释一下\后面跟着三个数字代表8进制,8进制的130转换为10进制是88,那为什么最后打印的是X呢(以%c字符打印),其实X的ACLL值是十进制的88。
相同的道理\x后面跟两个数字代表的是十六进制数字

int main()
{printf("%c\n", '\130');//8进制的130是十进制的多少呢?X   -- ASCII码值是88printf("%c\n", '\101');// 8进制101  转换为十进制为65  对应ASCLL值是 Aprintf("%c\n", '\x30');//  十六进制x30 十进制是48 -ASCLL值对应 '0' return 0;
}

个人解释:那什么是ASCLL值呢,我们的键盘可以打出各种各样的字符,比如:~!#¥%……&*()1,R…计算机上存储的是二进制,那这样的字符怎样存储呢,这些字符不好存储,那么我们可以给这些字符编个号,比如A-65,B-66按照这样给每个字符都编了号,最后产生了一张ASCLL码表,表里给每一个字符都有对应的一个值,叫ASCLL码值。


笔试题:
这里我们来看一道笔试题,printf("%d\n", strlen(“c:\test\328\test.c”));这个字符串的长度会是多少呢?

个人解释:c :\t e s t \32 8 \t e s t . c分别为一个字符,总共为14个字符,为什么不是\328算一个字符,因为八进制没有8。

int main()
{printf("%d\n", strlen("abc")); //值为3printf("%d\n", strlen("c:\test\328\test.c"));return 0;
}

5.3注释

  1. 代码中有不需要的代码可以直接删除,也可以注释掉
  2. 代码中有些代码比较难懂,可以加一下注释文字
#include <stdio.h>
int Add(int x, int y) {return x+y; }
/*C语言风格注释
int Sub(int x, int y)
{return x-y;
}
*/
int main()
{//C++注释风格//int a = 10;//调用Add函数,完成加法printf("%d\n", Add(1, 2));return 0; }

注释有两种风格:

  • C语言风格的注释 /* xxxxxx */
    缺陷:不能嵌套注释
  • C++风格的注释 //xxxxxxxx
    可以注释一行也可以注释多行

6、选择语句


如果你好好学习,校招时拿一个好offer,走上人生巅峰。
如果你不学习,毕业等于失业,回家卖红薯。
这就是选择!
个人解释:在这里先让大家感受一下分支语句,点到为止,后期我们会详细讲解

int main()
{int input = 0;//输入的值printf("加入我们:>\n");printf("那要好好学习吗(1/0)?>:");scanf("%d", &input);if (input == 1)   //判断{printf("好offer\n");}else{ printf("卖红薯\n");}return 0;
}

7、循环语句


有些事必须一直做,比如我日复一日的讲课,比如大家,日复一日的学习。

C语言中如何实现循环呢?

  • while语句-讲解
  • for语句(后期讲)
  • do … while语句(后期讲)
//while循环的实例
#include <stdio.h>
int main()
{printf("加入我们\n");int line = 0;while(line<=20000){line++;printf("我要继续努力敲代码\n");}if(line>20000)printf("好offer\n");return 0;
}

8、函数


用函数完成两个数的相加(先了解后边会细讲)

int Add(int x, int y)
{int z = 0;z = x + y;return z;
}int main()
{int num1 = 0;int num2 = 0;scanf("%d%d", &num1, &num2);//int sum = num1 + num2;//函数的方式解决int sum = Add(num1, num2);printf("%d\n", sum);return 0;
}

函数的特点就是简化代码,代码复用。

9、数组


个人解释:如果我们要存储十个数字的话,用我们之前所学的知识只能创建10个变量分别存储.

int main()
{int a = 1;int b = 2;int c = 3;int d = 4;....return 0;
}

9.1数组定义

int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素

9.2 数组的下标

比如:

int arr[10] = {0};
//如果数组10个元素,下标的范围是0-9

9.3 数组的使用

用数组的话存储1-10的数字,怎么存储?
C语言中给了数组的定义:一组相同类型元素的集合

个人解释:数组arr[10],10代表有10各元素分别是1~10。遍历数组当中元素时用循环来遍历,数组的下标默认是从0开始的。

int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9,10};int i = 0;                //数组是用下标来访问的,下标默认从0开始while (i < 10){printf("%d ", arr[i]);i++;}char ch[5] = {'a', 'b', 'c'};//不完全初始化,剩余的默认为0return 0;
}

10、操作符


简单介绍为主,后面重点讲。

  • 算术操作符
    个人解释:①在c语言中,x 用 *代替。②÷左右两边操作数类型相同时,结果与操作数类型相同;如果左右两边操作数类型不同时,计算结果的数据类型与较高级别保持一致。如果被除数和除数中有一个为负值,则舍入方向不固定。大多的C语言编译器采用向零取整。③%运算符要求左右两边的操作数必须为整数,最终结果也是整数。

+    -    *   /    %(取模)

  • 移位操作符

>> (右移)       <<(左移)

个人解释: 左移操作符移动的是二进制位。 被向左移动的话a=2, 2的二进制序列是10,因为a是放在整型里边去的,整型是占4个字节,一个字节8个比特位,所以我要写出a的二进制序列的话那得写出32个比特位“ 00000000 00000000 00000000 00000010 ”那这个时候2的二进制序列是这样存的,那把a的二进制序列向左移动1位如下图,移动后的空位补0,那二进制100是十进制的4,所以最终结果打印整型为4.

int main()
{int a = 2;int b = a << 1;printf("%d\n", b);return 0;
}
  • 位操作符

&(按位与)     ^(按位异或)     |(按位或)

  • 赋值操作符

=    +=    -=    *=    /=    &=    ^=    |=    >>=    <<=

  • 单目操作符(有一个操作数)

!             逻辑反操作
-             负值
+             正值
&             取地址
sizeof           操作数的类型长度(以字节为单位)
~            对一个数的二进制按位取反
- -             前置、后置- -
++             前置、后置++
*             间接访问操作符(解引用操作符)
(类型)           强制类型转换

sizeof也可以计算数组的大小

int main()
{//10*4 = 40 int arr[10] = { 0 };printf("%d\n", sizeof(arr));//计算的是数组的总大小,单位是字节,10个元素一个元素占4个字节printf("%d\n", sizeof(arr[0]));//4int sz = sizeof(arr) / sizeof(arr[0]);  //如何计算一个数组的元素个数printf("%d\n", sz);return 0;
}


~ :对一个数的二进制按位取反

个人解释:把所有二进制位中的数字,原来是1变成0,0变成1。
一个整数的二进制表示有三种:原码、反码、补码
整数在内存中存储的是补码
大家注意原、反补的计算是针对负数的。正整数原、反、补相同
例如:-1
原码:10000000 00000000 00000000 00000001 ( 最高位表示符号位,最高位1表示负数)
反码:11111111 11111111 11111111 11111110 ( 符号位不变,其他位按位取反)
补码:11111111 11111111 11111111 11111111 (补码在反码的基础上加1)

0的二进制:00000000 00000000 00000000 00000000 32位
~a的结果: 11111111 11111111 11111111 11111111 32位 (按位取反后的值是补码)
反码:   11111111 11111111 11111111 11111110 (在补码基础上-1)
原码:   10000000 00000000 00000000 00000001 (最后除最高位其他位按位取反)
最终结果为-1

int main()
{int a = 0;printf("%d\n", ~a);~ 按位取反return 0;
}


- -            前置、后置- -
++            前置、后置++

前置++,先++,后使用

int main()
{int a = 10;int b = ++a;//前置++,先++,后使用printf("%d\n", b);//11printf("%d\n", a);//11return 0;
}

后置++,先使用,再++

int main()
{int a = 10;int b = a++;//后置++,先使用,再++printf("%d\n", b);//10printf("%d\n", a);//11return 0;
}

(类型)           强制类型转换

int main()
{int a = (int)3.14;printf("%d\n", a);return 0;
}

  • 关系操作符

=       >
<
<=
!=       用于测试“不相等”
==       用于测试“相等”

  • 逻辑操作符

&&         逻辑与
||           逻辑或

  • 条件操作符(三目操作符)

exp1 ? exp2 : exp3
exp1成立,exp2计算,整个表达式的结构是exp2的结果
exp1不成立,exp3计算,整个表达式的结构是exp3的结果

int main()
{int a = 0;int b = 3;int max = 0;//if (a > b)//   max = a;//else//   max = b;max = a > b ? a : b;   //同等于上面注释的代码printf("%d\n", max);return 0;
}
  • 逗号表达式

exp1, exp2, exp3, …expN
逗号隔开的一串表达式,整个逗号表达式的结果是它最后一个表达式的结果

int main()
{//(2, 4 + 5, 6);int a = 0;int b = 3;int c = 5;//a=5       c=1        b=3int d = (a = b + 2, c = a - 4, b = c + 2);//逗号表达式,是从左向右依次计算的//整个表达式的结果是最后一个表达式的结果printf("%d\n", d);return 0;
}
  • 下标引用、函数调用和结构成员

[]     ()    .     ->

下标引用操作符

函数调用操作符

int main()
{//调用函数的时候,函数名后边的()就是函数调用操作符printf("hehe\n");printf("%d", 100);return 0;
}

11、常见关键字


C语言提供的关键字

  1. C语言提供的,不能自己创建关键字
  2. 变量名不能是关键字

auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while
注:关键字,先介绍下面几个,后期遇到讲解。

auto

int main()
{{auto int a = 10;//进入{}自动创建,出了{}自动销毁的 - 自动变量//auto一般在局部变量 省略掉了//auto 新的C语言语法中也有其他用法 - 暂时不考虑}return 0;
}

register:寄存器关键字

个人解释:用这个关键字创建的变量建议放到寄存器当中,是不是最终放到寄存器里边去是我们的编译器说的算,可是为什么要放到寄存器中呢?在计算机中,数据可以存储到寄存器、高速缓存、内存、硬盘、网盘当中。那么网盘所给的空间是最大的,一般2个T左右,其次是硬盘500G,其次是内存8G~16G,再其次是高速缓存,几十MB,最后是寄存器,空间会更小。如图,金字塔越往上,造价越高速度越快,但是空间越小。随着技术的发展CPU的处理速度越来越快,而内存的读写速度并没有跟上CPU的处理速度,就会发生CPU处理速度越来越快,内存读写速度跟不上,就会导致CPU在很多情况下会闲置。那我们会在内存之上提供高速缓存,高速缓存之上再提供寄存器,CPU拿数据只需去寄存器里拿,整体我们的效率会大大提升,寄存器的速度非常快的话,那我们将那些大量频繁被使用的数据,放在寄存器当中,那这样会提升我们的效率。
那现在我们的编译器已经非常非常聪明了即使你不写register,他认为某些数据该放到寄存器当中,它会自动放到寄存器里面去。

int main()
{//大量/频繁被使用的数据,想放在寄存器中,提升效率register int num = 100;//建议num的值存放在寄存器中return 0;
}

signed :有符号的
static:静态的
struct:结构体
union:联合体(共用体)
void:无

11.1 关键字 typedef

typedef 顾名思义是类型定义,这里应该理解为类型重命名。

个人解释:unsigned int 这个类型的名字太长了,我们为了简化可以将这个类型的名字重新命名,u_int就是unsigned int的别名

比如:

typedef unsigned int u_int;int main()
{unsigned int num = 100;u_int num2 = 100;  //与上面一条代码一模一样return 0;
}

11.2 关键字static

在C语言中:
static是用来修饰变量和函数的

11.2.1 修饰局部变量

  1. 修饰局部变量-称为静态局部变量,变量出局部{}不销毁继续保留,改变了局部变量的生命周期(本质上改变了变量的存储类型)

个人解释:内存分为三个区,栈区、堆区、静态区。当我们的a没有被修饰的时候它是放在栈区上的,当被static修饰之后,它直接放到静态区,那本质a从栈区变成静态区,改变的是它的存储类型。静态区静态变量和全局变量的声明周期一样

void test()
{int a = 1;a++;printf("%d ", a);
}int main()
{int i = 0;while (i<10){test();i++;}return 0;          //结果为10个2
}
void test()
{static int a = 1;a++;printf("%d ", a);
}int main()
{int i = 0;while (i<10){test();i++;}return 0;  //结果是2到11
}

11.2.2 修饰全局变量

修饰全局变量-称为静态全局变量

个人解释:没用static修饰全局变量之前,整个工程都可以使用。

个人解释:用static修饰外部全局变量之后,我即使声明了我依然无法使用它,static修饰全局变量,使得这个全局变量只能在自己所在的源文件内部可以使用,其它源文件不能使用。
全局变量在其他源文件可以被使用,是因为全局变量具有外部链接属性,但是被static修饰之后就变成了内部链接属性,其他源文件就不能链接到这个静态的全局变量了。

//extern 声明外部符号的
extern int g_val;int main()
{printf("%d\n", g_val);return 0;
}

11.2.3 修饰函数

修饰函数-称为静态函数

这里和全局变量时非常相似的

static修饰函数,使得函数只能在自己所在的源文件内部使用,不能再其它源文件内部使用。
本质上static是将函数的外部链接属性变成内部链接属性。

//声明函数
extern int Add(int x, int y);int main()
{int a = 10;int b = 20;int sum = Add(a, b);printf("sum = %d\n", sum);return 0;
}

12、define 定义常量和宏


1.define定义常量

//define 是一个预处理指令
#define MAX 1000int main()
{printf("%d\n", MAX);return 0;
}
  1. define 定义宏
#define ADD(X,Y) ((X)+(Y))int main()
{printf("%d\n", 4*ADD(2, 3));return 0;
}

13、指针


13.1 内存

  • 内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。
    所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。
    为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地
    址。

个人解释:其实我们平时听到的32位机器和64位机器,实际上是有32/64根地址线(物理线)它可以通电,通电后正电是1负电是0。正负电之分就产生了1和0这样的信号,因为我们把电信号转换成数字信号,这就变成了0 和1组成的二进制序列。那么32根地址线产生的二进制序列的信号它的可能性就是32个全0到32个全1,它会产生2的32次方个这样的序列,这些序列都可以作为内存的编号,我们就把这个编号称为这个内存单元的地址。
那我们一个内存单元该给多大空间呢?假如一个地址是1比特的话,存储char类型是1字节
那就是8个比特就会占用8个地址,这分的有点过于细致。如果一个内存单元是一个字节的话就非常合适。最终一个内存单元取一个字节(byte)

变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。
取出变量地址如下:

int main()
{int a = 10;//a在内存中要分配空间的 - 4个字节printf("%p\n", &a);//%p 专门用来打印地址的return 0;
}

个人解释:&a拿到的是四个字节中的第一个字节的地址0x010FFAE8,0a是第一个字节,后面三个分别是第二第三第四个字节,E8是0a的地址。

个人解释:&a拿到它也是个值,这个值要存起来,得有块空间,假设这块空间是pa,pa是用来存放地址的,在C语言中pa叫是指针变量

int main()
{int * pa = &a;//pa是用来存放地址的,在C语言中pa叫是指针变量,类型为int* //* 说明 pa是指针变量//int 说明pa指向的对象是int类型的char ch = 'w';char * pc = &ch;return 0;
}

个人解释:我们发现改a的值可以不通过a来改变,把a的地址交给pa,pa解引用就可以找到a,*叫解引用操作符

int main()
{int a = 10;int* pa = &a;*pa = 20;//* 解引用操作 , *pa就是通过pa里边的地址,找到a,把a该掉 printf("%d\n", a);return 0;
}

个人解释:当你取出num的地址时,实际上取出的是四个字节的第一个地址(44),44要存到p里面去,这时候p就相当于指向了num,相当于蓝色部分的p里面存的地址指向了num,所以当我们*p的时候其实找到的就是num,我可以把它改成20。

13.2 指针变量的大小

32位机器上一个地址是32个比特位,就是4字节
64位机器上一个地址是64个比特位,就是8字节

#include <stdio.h>
//指针变量的大小取决于地址的大小
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{printf("%d\n", sizeof(char *));   //结果都是4printf("%d\n", sizeof(short *));printf("%d\n", sizeof(int *));printf("%d\n", sizeof(double *));return 0; }

结论:指针大小在32位平台是4个字节,64位平台是8个字节。

14、结构体


结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
结构体可以让C语言创建新的类型出来
例如:

//创建一个学生
struct Stu
{char name[20];//成员变量int age;double score;
};//创建一个的书的类型
struct Book
{char name[20];float price;char id[30];
};int main()
{struct Stu s = {"张三", 20, 85.5};//结构体的创建和初始化printf("1: %s %d %lf\n", s.name, s.age, s.score);//结构体变量.成员变量struct Stu * ps = &s; //当我们把结构体交给一个指针的时候,他也能打印相应的内容printf("2: %s %d %lf\n", (*ps).name, (*ps).age, (*ps).score); //*ps解引用就是sprintf("3: %s %d %lf\n", ps->name, ps->age, ps->score);  //ps指向对象的名字namereturn 0;
}


本章完

c生万物【第一章 初识c语言】相关推荐

  1. C Prime Plus 第一章 初识C语言

    初识C语言 C的历史和特性 选择C语言的理由 C语言的应用范围 计算机能做什么 高级计算机语言和编译器 语言标准 第一个ANSI/ISO C 标准 C99标准 C11标准 使用C语言的7个步骤 编译机 ...

  2. 【维生素C语言】第一章 - 初识C语言

    声明:由于作者水平有限,本文难免有错误和不准确之处,本人也很想知道这些错误,恳望读者批评指正. [联系方式]1300300100@qq.com [更新记录]2020年4月4日(第三次更新 ) [勘误记 ...

  3. 第一章 初识Mathematica

    第一章  初识Mathematica   1.Mathematica是什么 Matematica是由美国Wolfram公司研究开发的一个著名的数学软件,它提供了非常强大的功能,能够完成符号运算.数学图 ...

  4. 《起跑吧,Opa》 -- 中译本 第一章 初识Opa

    第一章 初识opa 本章,你将初识opa.你将学习如何安装Opa,编写opa程序以及熟悉Opa开发周期中的各个步骤. 安装opa 需要你预先从opa网站(http://opalang.org/)下载适 ...

  5. 第一章 初识EmguCV

    第一章 初识EmguCV 1.1 EmguCV的基本介绍 1.1.1 计算机视觉.OpenCV和EmguCV 计算机视觉是一门研究如何使机器"看"的科学,更进一步的说,就是是指用摄 ...

  6. 第一章 初识HTML

    第一章 初识HTML 学习HTML: 开发网页.微信小程序.跨端界面开发.web游戏 hyper text markup language 超文本标记语言 网页的源码,解释和执行 w3c:万维网联盟/ ...

  7. 第一章 初识OpenHarmony

    序言 本书以3W1H教学法对每个知识点进行多维度介绍,笔者认为这样写更符合人类对新知识的学习.本书以教学场景续写,一章为半天知识点. 本书读者对象 阅读本书您需要具备html.css.js基础知识,所 ...

  8. 第一章 初识Docker

    第一章 初识Docker 1.1 什么是Docker Docker开源项目 Docker是基于Go语言实现的云开源项目,诞生于2013年初,最初发起者是dotCloud公司.Docker自开源后受到广 ...

  9. 尚学堂百战程序员1573题---答案总结第一章 初识Java

    第一章 初识Java 1. 你学习编程的目的是什么?学习编程最快的办法是什么? 答:我觉得的我喜欢计算机,我认为计算机是一个很神奇的东西,所以我要学计算机专业,同时,我认为学计算机学编程是一个比较容易 ...

最新文章

  1. C#程序如何对接比特币钱包节点?
  2. C++、C#控制台应用程序暂停下来的方法
  3. Nginx负载均衡+tomcat+session共享
  4. Redis的常用命令——set的常用命令
  5. jquery监听滚动条
  6. 基于python的系统构建_搭建一个基于python的深度学习环境
  7. spring事务管理几种方式(转)
  8. 【转载】令人作呕的OpenSSL,转自CSDN博主Bomb250
  9. LeaRun.Java表单快速开发工具
  10. 共同创业五年,技术总监却突然就这么离职了
  11. centos6 安装 directAdmin
  12. Groovy探索之MOP 十五 方法名的动态性(2)
  13. html 带箭头的提示框,css实现对话框-带箭头提示框
  14. 人人网的相册里图片上传功能是怎样实现的
  15. react项目中实现打印预览功能
  16. 金海佳学C++primer 练习9.44
  17. 李希贵:教育改革最大的阻力来自我们内心
  18. 远程缝制葡萄皮,成本仅1万元,华为200万年薪博士杰作
  19. PYTHON:PYQT5 实现 pdf 合并与分割
  20. java大神的成神之路

热门文章

  1. 精品新年大礼包V2008 CD DVD 全发布
  2. 任何一个合数都可以写成几个质数相乘的形式
  3. springboot毕设项目课堂考勤管理系统设计与实现o2j18(java+VUE+Mybatis+Maven+Mysql)
  4. 计算机网络中的协议是什么意思,常用的网络协议有哪些,分别是什么含义
  5. 直播预告|生成对抗网络专题复现课今晚开课!
  6. 学习结构体,以及使用方法
  7. PL/SQL(英文版)中如何改变 字体大小
  8. RGSSAD加密方案分析
  9. DTOJ #5274. 割葱
  10. stm32的定时器写入小数给ccr和arr