初识C语言

一、C语言的历史

1.C语言的诞生

C语言的前身是Martin Richards开发的BCPL语言。1970年Ken Thompson对BCPL语言进行了改进,发明了B语言。
972年Dennis M.Ritchie又在B语言的基础上开发出了C语言。
当时,Ritchie和Ken Thompson等人一同致力于小型机操作系统UNIX的开发。UNIX操作系统最初是用汇编语言开发的,之后用C语言进行了重写。
C语言是为了移植早期的UNIX而开发出来的,所以从某种意义上说“C语言是UNIX的副产品”。
不只是UNIX本身,就连运行在UNIX系统上的许多应用程序也是接二连三地使用C语言开发出来的。
因此,C语言首先普遍应用于UNIX世界,接着又凭借其势不可挡的魅力在大型计算机和个人计算机领域得到了广泛普及。
而且C语言对C++和Java等后来产生的很多编程语言也都产生了直接或间接的影响。

2.C语言的标准演化

Ritchie与Brian W.Kernighan合著了一本C语言教材:The C Programming Language,Prentice-Hall,1978(中文版名为《C程序设计语言》)
热心的读者们结合两位作者的姓氏首字母“K&R”,将其作为书的昵称。在K&R的附录部分收录了C语言规范的参考手册(Reference Manual)。这个语言规范就是C语言最初的标准。
但是K&R的参考手册中的C语言规范还存在不少未完全明确的部分。而且,随着C语言广泛的普及,衍生出了许多具有不同扩展功能的C语言。这就导致C语言的可移植性下降。
这时,制定C语言国际标准应运而生。
国际标准化组织ISO和美国国家标准学会通力合作完成了这项任务。
1989年12月,制定了美国国家标准即“C89”标准。
1990年12月,制定了国际标准即“C90”标准。
也许是因为ANSI标准比ISO标准制定得早,加上ANSI在日本的知名度较高,很多人将遵循标准规范的C语言叫做ANSI C
1993年,日本也制定出了相同内容的标准。
1994年12月,中国发布了C语言的国家标准,采用的即是上述“C90”标准。
1999年,对C语言的规范进行了修订,加入了可变长数组、long long int型等内容,即“C99”标准,但该标准没有得到广泛应用。

二、初识C语言语法

1. 第一个C语言程序

#include <stdio.h>//使用scanf和printf时,要包含该头文件
int main()
{
	printf("hello world\n");//printf是一个打印函数,可以将hello world打印在屏幕上
	return 0;
}

main函数是整个程序的入口,在一个工程里面有且只能有一个。

2. 数据类型

C语言中常见的数据类型:

char
short
int
long
long long
float
double

每种数据类型的大小是多少呢?
我们可以用下面这段代码来计算。

#include <stdio.h>
int main()
{
	printf("%d", sizeof(char));//sizeof是一个单目操作符,可以用来计算变量和类型所占内存空间的大小,单位是字节。
	printf("%d", sizeof(short));
	printf("%d", sizeof(int));
	printf("%d", sizeof(long));
	printf("%d", sizeof(long long));
	printf("%d", sizeof(float));
	printf("%d", sizeof(double));
	return 0;
}

计算出来的结果是:

char占1个字节
short占2个字节
int占4个字节
long占4个字节
long long占8个字节
float占4个字节
double占8个字节

小知识点:1.C语言标准中规定long的大小是大于或等于int,本代码是在vs下运行出来的,可见vs采用的是long的大小等于int这种情况。
2.在C语言中,直接写出3.1默认是double类型,写成3.1f才是float类型。
3.计算机体系结构从上到下分为应用程序、操作系统、驱动程序、硬件,C语言擅长进行操作系统及以下的底层开发。

3. 变量和常量

3.1 变量

  1. 定义变量的方法:

int a = 0;//数据类型 + 变量名就可以创建一个变量,一般情况下,创建变量的同时还要进行初始化。
char ch = ‘w’;
float f = 3.1f;

小知识点:C语言中用’‘引起来的才叫字符,例如’a’,‘b’;用"“引起来的叫字符串,例如"abcdef”

  1. 变量的分类

局部变量:大括号内定义的变量。
全局变量:大括号外定义的变量。

注意:局部变量和全局变量同名时,局部变量优先。
我用一个代码来解释上面这句话。

#include <stdio.h>
int a = 0;
int main()
{
	int a = 10;
	printf("%d\n", a);
	return 0;
}

上面这段代码在打印时,输出的是局部变量a的10,并非全局变量a的0,因为局部变量和全局变量同名时,局部变量优先。
3. 变量的使用
通过一段代码来演示下如何使用变量:

#define _CRT_SECURE_NO_WARNINGS 1//在vs环境下,使用scanf会报错,使用这段代码可以让vs不报错
#include <stdio.h>
int main()
{
	//先创建两个整型变量,用来存储两个整形数据
	int num1 = 0;
	int num2 = 0;
	//通过scanf函数向两个变量输入数据
	scanf("%d%d", &num1, &num2);//scanf是一个输入函数,通过键盘向黑框框中输入数据;
	//将num1与num2相加的和,打印到黑框框中
	printf("%d\n", num1 + num2);//printf是一个打印函数,把数据打印到黑框框中
	return 0;
}
  1. 变量的作用域和生命周期

4.1 变量作用域:哪里可以使用哪里就是它的作用域。
局部变量的作用域就是它所在的局部范围,即它所在的大括号{}就是它的作用域
全局变量的作用域是整个工程,例如在a.c源文件定义的全局变量num,在b.c源文件用extern int num;声明一下就可以直接在b.c源文件使用了
4.2 变量的生命周期:指的是变量从创建到销毁的一个时间段
局部变量的生命周期:进入局部范围生命周期开始,出局部范围生命周期结束。
全局变量的生命周期:整个程序的生命周期。

3.2 常量

  1. 字面常量

直接能看到数值的常量就是字面常量。 例如:1(整型字面常量) “abcdef”(字符串字面常量) ‘c’(字符字面常量)

  1. const修饰的常变量

const修饰的常变量的特点:加上了常属性,所以不能被直接修改,但它依然是变量。

用一段代码来解释一下:

int main()
{
	const int a = 10;
	a = 5;
	return 0;
}

上面的代码在运行时是会报错的,因为const修饰的变量是不能被直接修改的。
3. #define定义的标识符常量

#define MAX 100
int main()
{
	int a = MAX;
	return 0;
}
  1. 枚举常量

枚举类型里面列出的可能取值叫做枚举常量,枚举常量默认是从0开始,向下递增1,但可以给每个枚举常量赋初始值。

int main()
{
	enum Sex
	{
		MALE,
		FEMALE,
		SERECT
	};
	return 0;
}

4. 字符串、转义字符、注释

4.1 字符串

  1. 用""引起来的一串字符就叫字符串。
  2. 字符串末尾有个’\0’,作为字符串的结束标志,在用strlen计算字符串长度时,'\0’不算做字符串内容。
#include <stdio.h>
#include <string.h>//使用strlen函数要包含该头文件
int main()
{
	char arr[] = "abcdef";//用字符数组存储字符串
	printf("%d\n", strlen(arr));//计算'\0'之前出现了多少个字符
	return 0;
}

4.2 转义字符

转义字符可以简单理解为在普通字符前加了个\转变了其原来意思的字符。
下面是C语言中常见的转义字符

在这里插入图片描述
下面对以上的转义字符进行一些简单的解释:

  1. \?
    在C语言中有一个三字母词??),如果你打印??),就会打印成]。(三字母词在早期的编译器上才会有)
    在三字母词前面加一个\,就不会将三字母词打印成]了,会原原本本的打印出??),因为\和三字母词的第一个?结合成了转义字符?
  2. '和"
    用一段代码解释一下:
#include <stdio.h>
int main()
{
	//打印一个字符'
	printf("%c\n", '\'');//只有写成'\''才能打印出',直接写'''的话,前两个单引号会结成一对儿,最后一个单引号落单了,就会报错。
	//打印一个字符串,字符串的内容是"
	printf("%s\n", "\"");//这个也是如此,只能写成"\"",否则最后一个单引号会落单,然后程序报错。
	return 0;
}
  1. \用于表示一个普通字符\,因为在C语言中,一个\是转义字符里面的\,在打印的时候是打印不出来的,\才是普通的字符\,才可以打印出来。
  2. \ddd和\xdd
    ddd表示\后面跟1~3个八进制数字,dd表示\后面跟2个16进制数字。
    \ddd这个转义字符表示\后面的八进制数字作为ASCII码值所对应的字符;\dd表示\后面的16进制数字作为ASCII码值所对应的字符。
    剩下的转义字符认识一下就行,见了面知道它是转义字符就行。

下面用一个代码展示下转义字符的奥秘:

#include <stdio.h>
int main()
{
	printf("%d\n", strlen("c:\test\628\test.c"));
	return 0;
}

猜猜这段代码打印出来的结果是多少?
有人说14,有人说15,还有人巴拉巴拉。
但是真相只有一个!!!
这段代码的运行结果是14,因为有三个转义字符’\t’,‘\62’,‘\t’,知道这串字符有这三个转义字符,你就能算出正确答案了。
注意:算出是15个的原因,你可能把’\628’,当做一个转义字符了,但是你要看清楚,\后面如果没有x的话,跟1~3个八进制数字才能算做一个转义字符,8可不是八进制数字哦,别被迷惑了。

4.3 注释

注释有两个作用:

  1. 当你写的代码不想要的话,你可以注释掉
  2. 你想给代码加一些解释时,可以写一些注释
    C语言的注释符号是//,缺点是不可以嵌套注释;C++的注释符号是//,在C99中C语言也引入了该注释符号,这个比较常用,非常方便,可以嵌套使用。

5. 选择语句、循环语句

5.1 选择语句

C语言中的选择语句有if…else, switch…case,但因为是初识C语言,先介绍一个较为简单的if…else语句吧。
下面看一段代码:

#include <stdio.h>
int main()
{
	int a = 3;
	int b = 2;
	if(a > b)//if后面跟条件
	{
		printf("hehe\n");
	}
	else
	{
		printf("haha\n");
	}
	return 0;
}

上面这段代码的意思就是如果a > b就打印hehe,否则打印haha。

5.2 循环语句

C语言中的循环语句有for,while,do…while,下面用代码介绍一个较为简单的while语句。

//用while语句,在屏幕上打印一百个"憨憨"
#include <stdio.h>
int main()
{
	int i = 0;
	while(i < 100)
	{
		printf("憨憨\n");
		i++;
	}
	return 0;
}

6. 函数

用一段代码来解释下:

//写一个求两个数的和的函数
int Add(int x, int y)//返回值类型,函数名,形参
{
	return x + y;//大括号包起来的叫函数体
}

可以把函数理解为工厂,把原料(实参)给它,它就可以给你生产出产品(返回值)。

7. 数组

7.1 数组的定义

数组的定义有三种方法:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//完全初始化
int arr[10] = {1,2,3};//不完全初始化
int arr[] = {0};//在创建数组时没有指定大小,这个数组的大小由初始化决定。

7.2 数组的下标

C语言规定数组中每个元素都有下标,下标是从0开始的。
例如:数组有10个元素,则下标范围是0~9

7.3 数组的使用

可以用scanf函数向数组中放入数据,可以用printf函数打印数组里面的数据:

#define _CRT_SECURE_NO_WARNINGS 1//让vs环境下的scanf不报错
#include <stdio.h>
int main()
{
	int arr[10] = {0};
	//向数组中下标为0~9的位置放入数据
	int i = 0;
	while(i < 10)
	{
		scanf("%d", &arr[i]);
		i++;
	}
	//打印数组中下标为0~9的元素
	i = 0;
	while(i < 10)
	{
		printf("%d ", arr[i]);
		i++;
	}
	return 0;
}

8. 操作符

8.1 算术运算符

算数运算符有+,-,*,/, %
前三个没什么好讲的,着重讲一下后两个:

  1. /两边至少有一个小数才执行小数除法
  2. 任何数%n,得到的余数都在0~n - 1范围内

8.2 移位操作符

移位操作符有>>和<<

8.3 位操作符

位操作符有&,^,|

8.4 赋值操作符

赋值操作符有= += -= *= /= &= ^= |= >>= <<=

8.5 单目操作符

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

8.6 关系操作符

>
>=
<
<=
!= 用于测试“不相等”(不能用于比较字符串)
== 用于测试“相等”(不能用于比较字符串,比较字符串要用strcmp)

8.7 逻辑操作符

&& 逻辑与
|| 逻辑或

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

exp1 ? exp2 : exp3
这个操作符的意思是如果exp1为真,exp2的结果为整个表达式的结果,否则exp3的结果为整个表达式的结果。
再用一段代码举个例子:

int main()
{
	int a = 3;
	int b = 2;
	int c = (a > b) ? 5 : 6;//如果a > b 则把5赋给c,否则把6赋给c
	return 0;
}

8.9 逗号表达式

exp1, exp2, exp3, …expN
逗号表达式是从左往右依次执行,最后一个表达式的结果为整个表达式的结果。
举个例子:

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 3;
	int c = 5;
	printf("%d\n", (a = 3, b = b + 2, c = a + b));//第一个表达式a变成了3,第二个表达式b变成了5,第三个表达式c = a + b,即3 + 5,所以最后的结果是8
	return 0;
}

8.10 下标引用、函数调用和结构成员

[] (arr[3] = 0里面的[]就是下标引用操作符,也可以写成3[arr] = 0,[]的操作数分别是arr和3,但是int arr[10] = {0}里面的[],不是下标引用操作符,它只是在创建数组时所用的普通符号)
()(Add(2,3)里面的()就是函数调用操作符,()的操作数分别是Add,2,3)
. ->

9. 常见关键字

在这里插入图片描述
变量名不能是关键字

  1. auto(自动的)—修饰局部变量的,局部变量都是自动创建,自动销毁,所以都有auto来修饰,但auto可以省略不写
  2. const(修饰变量和指针)
  3. register(寄存器关键字)
    例如:register int a = 10;(建议把变量a放到寄存器里面去)
  4. typedef(类型重定义)
  5. union(联合体,共用体)
  6. static(修饰局部变量(出了作用域也不会销毁),修饰全局变量(static修饰的全局变量只能在所在源文件使用;原因:全局变量是具有外部链接属性的,被static修饰后外部链接属性变成了内部链接属性,作用域变小了),修饰函数(static修饰的函数只能在所在源文件使用,原因:static使得函数的外部链接属性变成了内部链接属性,作用域变小了))
  7. extern(声明外部符号)
    例如:extern int a;(在a源文件创建的全局变量,b源文件想使用,就得这样声明)
    extern int Add (int,int);((在a源文件创建的函数,b源文件想使用,就得这样声明))

额外知识:寄存器,高速缓存(cache),内存,硬盘(从右往左,速度越高,空间越小)
在这里插入图片描述
运行结果是多少?为什么?使用static int a = 3;又是啥结果?为什么?(内存分为栈区,堆区,静态区,普通的局部变量是放在栈区上的,进入作用域,变量创建,出了作用域就会销毁;static修饰的局部变量是放在静态区上的,出了作用域不会销毁仍然存在,下次进入作用域使用的是上一次遗留的值;改变了存储位置,由栈区->静态区,变量的生命周期也发生了变化)
栈区:放局部变量和函数的形参
堆区:放动态内存开辟的空间上的的数据(malloc,realloc,calloc)
静态区:放静态变量和全局变量(整个程序结束才销毁)

10. #define定义常量和宏

10.1 定义常量

在这里插入图片描述

10.2 定义宏(宏的名字一般都是大写)

在这里插入图片描述

11. 指针

在这里插入图片描述

  1. 内存中会划分成一个一个小的内存单元,每个内存单元的大小是一个字节;为了有效访问这一个个内存单元,又对内存单元进行编号,这些编号就被称为地址,也可叫做指针

  2. 在这里插入图片描述
    变量是在内存上开辟空间的,每个内存单元都是有编号的,所以变量也是有地址的;

  3. &a取出来的地址是一个16进制数值,需要用一个变量存储起来,存储地址的这个变量就叫做指针变量。口头语中的指针就是指针变量
    例如:int* pa = &a;
    pa就是一个指针变量,int*叫做整形指针类型,*说明pa是指针变量,int说明pa指向的对象是int类型

  4. *pa = 10;*是解引用操作符(间接访问操作符),*pa就是通过pa里面的地址,找到pa所指向的对象。
    在这里插入图片描述

  5. 指针变量的大小
    指针变量是用来存储地址的,所以指针变量的大小取决于存储一个地址需要多大的空间。
    电脑上的地址是由地址线传输的,电脑上的地址线要么是32根,要么是64根,电脑若在32位环境下,就有32根地址线,传输过来的就是由32个0和1组成的二进制数据,这个数据就是地址,32个二进制数字需要用4个字节来存储,所以在32位环境下指针变量的大小是4个字节,同理64位环境下指针变量的大小是8个字节。

小知识点:sizeof计算的结果是无符号整数类型的,打印格式要用%zu
打印地址用%p

12. 结构体

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 30
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值