初始C语言

本章目标:

基本了解C语言的基础知识,对C语言有一个大概的认识。
每个知识点就是简单认识,不做详细讲解,后期文章都会细讲。

本章重点:

  • 什么是C语言
  • 第一个C语言程序
  • 数据类型
  • 变量、常量
  • 字符串+转义字符+注释
  • 选择语句
  • 循环语句
  • 函数
  • 数组
  • 操作符
  • 常见关键字
  • define 定义常量和宏
  • 指针
  • 结构体

1. 什么是C语言

C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易
的方式编译、处理低级语言。

尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的
C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称超级电脑等作业平台。

二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制
定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。 [1] 目前2011年12月8
日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标
准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉
字编程。

C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。

其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。

引言:创建第一个项目
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

2. 第一个C语言程序

#include <stdio.h>
 int main()
 {
 	printf("hello word\n");
 	return 0;
 }
 //解释:
//main函数是程序的入口
//一个工程中main函数有且仅有一个

3. 数据类型

char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度浮点数
//C语言有没有字符串类型?

  • 为什么出现这么的类型?
  • 每种类型的大小是多少?
#include <stdio.h>
 int main()
 {
 	printf("%d\n", sizeof(char));//1字节
 	printf("%d\n", sizeof(short));//2字节
 	printf("%d\n", sizeof(int));//4字节
 	printf("%d\n", sizeof(long));//4字节
 	printf("%d\n", sizeof(long long));//8字节
 	printf("%d\n", sizeof(float));//4字节
 	printf("%d\n", sizeof(double));//8字节
 	printf("%d\n", sizeof(long double));//8字节
 return 0;
 }

注意:存在这么多的类型,其实是为了更加丰富的表达生活中的各种值。

类型的使用:

	char ch = 'w';
	int weight = 120;
 	int salary = 20000;

我们存入的数据例如’w’, 120等并不是直接将这些存入进去,而是通过转换成ASCLL码值形式存入进去
详细ASCLL值请看:https://baike.baidu.com/item/ASCII/309296

4. 常量、变量

生活中的有些值是不变的(比如:圆周率,性别(?),身份证号码,血型等等)
有些值是可变的(比如:年龄,体重,薪资)。
不变的值,C语言中用常量的概念来表示,变得值C语言中用变量来表示。

4.1 定义变量的方法

int age = 150;
float weight = 45.5f; 
//这里用的.5f是因为,当我们以45.5存储会是默认以double形式存储,在小数后面加上f就变成了float类型存储
char ch = 'w';

4.2 变量的命名

  • 只能由字母(包括大写和小写)、数字和下划线(_)组成。
  • 不能以数字开头。
  • 长度不能超过63个字符。
  • 变量名中区分大小写。
  • 变量名不能使用关键字。

4.3 变量的分类

  • 局部变量
  • 全局变量
#include <stdio.h>
int global = 2019;//全局变量
int main()
 {
 	int local = 2018;//局部变量
	//下面定义的global会不会有问题?
	int global = 2020;//局部变量
	printf("global = %d\n", global);
 	return 0;
 }

总结:

上面的局部变量global变量的定义其实没有什么问题的!
当局部变量和全局变量同名的时候,局部变量优先使用。

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

作用域

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

  1. 局部变量的作用域是变量所在的局部范围。
  2. 全局变量的作用域是整个工程。

生命周期

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

  1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
  2. 全局变量的生命周期是:整个程序的生命周期。

我们可以用一个简单的例子解释全局变量:
在这里插入图片描述

4.5 常量

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

  • 字面常量
  • const修饰的常变量
  • #define 定义的标识符常量
  • 枚举常量
#include <stdio.h>
 //举例   
enum Sex
 {
 	MALE,
 	FEMALE,
	SECRET
 };
 //括号中的MALE,FEMALE,SECRET是枚举常量
int main()
 {
 	3.14;//字面常量
	1000;//字面常量
	const float pai = 3.14f;   //const 修饰的常量
	pai = 5.14;//ok?
 	#define MAX 100           //#define的标识符常量        
	return 0;
}

对于常量的使用,我们可以把知识点延升到数组上,例如:int arr[10];这样定义是没有问题的,但是,int arr[a];这样的定义就有误。
这样我们不禁就在想,括号里面是不是只能装常量,我们可以通过define定义一个,比如:#define SIZE 10
就变成以下样子:int arr[SIZE];这样看下来,我们就能推断出括号里面确实是装载常量的。

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

5.1 字符串

"hello bit.\n"

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

#include <stdio.h>
 //下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
 {
 	char arr1[] = "bit";
 	char arr2[] = {'b', 'i', 't'};
 	char arr3[] = {'b', 'i', 't''\0'};
 	printf("%s\n", arr1);
	printf("%s\n", arr2);
	printf("%s\n", arr3);
 	return 0;
 }

输出结果:
在这里插入图片描述

从这里我们可以看到\0就是字符串的结束标志。

对于字符串的写法来说,会有很多正确的也有很多错误的写法,以下我们可以一一列举:
在这里插入图片描述

从上面的例子我们可以看出,arr里面有5个字符,没有位置存储’\0’,当我们输出字符arr时,找不到’\0’,所以就会输出一堆随机值,直到找到’\0’。
从以上我们可以看到,'\0’会占用数组里面的空间,但是不会当字符输出,而是会当结束标志停止往下寻找字符。

在这里插入图片描述

从这个例子跟上面的相对比,我们可以发现,使用单引号创建的话,需要自己手动增加’\0’。

5.2 转义字符

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

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

实际上程序运行的结果是这样的:
在这里插入图片描述

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

在这里插入图片描述
练习样例:
在这里插入图片描述

:即便是在字符串“ab\120c”中,我们通过strlen可以得到长度为4,从这可以看出虽然'\120'的转义是80的意思,但在字符串中在strlen计量数字中它还是归为一个。

那我们再往下面做一个练习题:

 //程序输出什么?
#include <stdio.h>
 int main()
 {
    printf("%d\n", strlen("abcdef"));
    // \32被解析成一个转义字符
    printf("%d\n", strlen("c:\test\328\test.c"));
    return 0;
 }

输出结果:
在这里插入图片描述

:我们通过第一个练习得知,转义字符在strlen里面只算做一个,这里有\t、\32、\t转义字符,这样我们就知道了14个是怎么计算得到得。

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. 选择语句

#include <stdio.h>
 int main()
 {
 int coding = 0;
 	printf("你会去敲代码吗?(选择1 or 0):>");
 	scanf("%d", &coding);
 if(coding == 1)
 {
 	prinf("坚持\n");
 }
 else
 {
 	printf("放弃\n");
 }
 return 0;
 }

7. 循环语句

  • while
  • do…while
  • for

通过以下例子练习循环

#include <stdio.h>

int main()
{
	//机翼部分
    for (int i = 0; i < 2; i++)
    {
        for (int t = 0; t < 4; t++)
        {
            printf(" ");
        }
        for (int y = 0; y < 2; y++)
        {
            printf("*");
        }
        for (int r = 0; r < 4; r++)
        {
            printf(" ");
        }
        printf("\n");
    }
    //机身部分
    for (int i = 0; i < 2; i++)
    {
        for (int r = 0; r < 10; r++)
        {
            printf("*");
        }
        printf("\n");
    }
    //机翼部分
    for (int i = 0; i < 2; i++)
    {
        for (int t = 0; t < 4; t++)
        {
            printf(" ");
        }
        for (int y = 0; y < 2; y++)
        {
            printf("*");
        }
        for (int r = 0; r < 4; r++)
        {
            printf(" ");
        }
        printf("\n");
    }
    return 0;
} 

输出结果:
在这里插入图片描述

再通过一个例子了解循环:

int main()
{
    int iq = 0;
    int eq = 0;
    while (scanf("%d", &iq) == 1)
    {
        if (iq > 140)
        {
            printf("真聪明!!!\n");
        }
        else
        {
            printf("继续努力!!!\n");
        }
    }
    return 0;
} 

从这段代码我们可以看到,主要的意思就是通过循环判断是否符合条件,最后进行输出。
这段代码最为核心的就是:scanf("%d", &iq) == 1
当我们正常输入自然没有影响,但是当你想要停下来的时候,就需要输入:ctrl + z

8. 函数

从以下例子我们可以去了解函数的应用:

int add(int a, int b)
{
    int sum = a + b;
    return sum;
}

int main()
{
    int a = 0;
    int b = 0;
    printf("请输入a和b:");
    scanf("%d %d", &a, &b);
    int sum = add(a, b);
    printf("sum = %d\n", sum);
    return 0;
} 

从这里我们可以看到函数的特点:简化代码,重复使用。

9. 数组

C语言中给了数组的定义:一组相同类型元素的集合

9.1 数组定义

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

9.2 数组的下标和使用

C语言规定:数组的每个元素都有下标,而下标是从0开始的。
数组可以通过下标进行访问。
比如:

//通过循环遍历出数组的每个元素
int main()
{
	int arr[10] = { 0 , 1, 2, 3, 4, 5, 6, 7, 8, 9};
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

在这里插入图片描述

10. 操作符

简单介绍为主,后面文章详解介绍。
引言:接下来这段学习中,我们会学到大量的操作符内容,我会挑出一些比较常见亦或者比较细节的点,带着大家做练习了解它们。

算术操作符

+   -   *   /   %

注:浮点数除法:至少保证除数和被除数一个是浮点型。

移位操作符

>>  <<

位操作符

&   ^   |

赋值操作符

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

单目操作符

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

很多人其实没有搞懂前置++和后置++的用法,那么- -自然也会难懂,其实理解起来没有那么困难。
我们通过下面例子来彻底搞懂此类用法。
在这里插入图片描述

从这段代码我们可以看到,输出的结果是a = 2,b = 2,我们来分析以下。
我们先简单区分以下前置++和后置++的区别,前置++就是在当前代码中变量+1,后置++就是当前代码不变,走到下面一行时就会+1,那我们带着这样的区别分析一下。
首先他这里用的前置++,我们上面说过前置++,当前代码变量+1,a+1赋值给b,也就是b = 2
注意的是,我们用的是++,它和单纯的+1是有区别的,简单拓展一下,比如:int b = a + 1和·int b = ++a,前面的不会改变a的结果,后面的则会改变a的结果。
所以呢当我们输出查看的时候,可以看到b = 2a = 2。为什么a也改变了,则是上面这个原因。
我们在这段代码中详细的介绍了区别以及输出结果,那么接下来我们在简单的查看一下后置++的结果,想必大家也是轻而易举就猜到了。

在这里插入图片描述

通过以上前置++和后置++的练习,想必已经掌握其中的规律了,那么我们再练习一下前置- -以及后置- -继续巩固一下吧。
在这里插入图片描述

在这里插入图片描述

他们的用法是一样的,接下来需要做的就是多练习多熟悉即可。

我们再来一个复杂的写法
在这里插入图片描述

首先说明,这种写法是不被推荐的。
其次,我们再来分析一下为什么会产生这种结果。
VS编译器对此产生的解释是:++a -> a = 2,++a->a = 3,++a->a = 4。
b = 4 + 4 + 4 = 12。
从以上分析可以看出,当一段代码出现多个前置针对一个变量的时候,先把前置产生的结果算出来,最后在把结果放到变量中赋值给b。
在不同编译器中,这段代码都产生歧义,并且可读性不高,不建议这样写法。

强转类型也值得简单学一下,看下面这个例子:
在这里插入图片描述

我们可以发现虽然3.14确实强制转换为了3,但是下面还是出现了警告,这种情况该如何避免呢?

在这里插入图片描述

在数据前面一个数据类型,即可完成强制转换且不会报错。

关系操作符

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

逻辑操作符

&&          逻辑与
||          逻辑或

&&:条件全真则为真,条件一假则为假。
||:条件有真则为真,条件全假则为假。

条件操作符

exp1 ? exp2 : exp3

表达式1 ?表达式2 : 表达式3;
如果表达式1为真,则选择2,否则为3。

从下面例子详细学习三目运算:
在这里插入图片描述

这里有一个细节就是:我们scanf里面需要输入的是:字符 空格 字符(也就是变量a空格变量b)。
如果把空格输入成其他的字符比如逗号句号等,那么就会导致读取错误,会出现错误的情况。

逗号表达式

exp1, exp2, exp3, …expN

逗号表达式是从左往右计算,但它的结果也是最后一个表达式的结果。例如以下:

在这里插入图片描述

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

[]  ()  .   ->

11. 常见的关键字

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

C语言提供了丰富的关键字,这些关键字都是语言本身预先设定好的,用户自己是不能创造关键字的。

在这里插入图片描述

11.1 关键字 typedef

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

比如:

//将unsigned int 重命名为uint_32, 所以uint_32也是一个类型名
typedef unsigned int uint_32;
int main()
 {
 //观察num1和num2,这两个变量的类型是一样的
	unsigned int num1 = 0;
 	uint_32 num2 = 0;
 	return 0;
 }

11.2 关键字 static

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

  1. 修饰局部变量 - 称为静态局部变量(进入作用域后创建,出作用域值依旧保留,直到程序结束,还给操作系统)
  2. 修饰全局变量 - 称为静态全局变量(使得这个全局变量只能在本源文件中使用)
  3. 修饰函数 - 成为静态函数(和以上特点一样)

11.2.1 修饰局部变量

//代码1
 #include <stdio.h>
 void test()
 {
 	int i = 0;
 	i++;
 	printf("%d ", i);
 }
 int main()
 {
 	int i = 0;
 	for(i=0; i<10; i++)
    {
 		test();
    }
 	return 0;
 }
 //代码2
 #include <stdio.h>
 void test()
 {
 //static修饰局部变量
	static int i = 0;
 	i++;
 	printf("%d ", i);
 }
 int main()
 {
 	int i = 0;
 	for(i=0; i<10; i++)
    {
 		test();
    }
 	return 0;
 }

对比代码1和代码2的效果理解static修饰局部变量的意义。
结论:

static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。

11.2.2 修饰全局变量

//代码1
//add.c
 	int g_val = 2018;
//test.c
int main()
{
	printf("%d\n", g_val);
 	return 0;
}
//代码2
//add.c
static int g_val = 2018;
//test.c
int main()
{
 	printf("%d\n", g_val);
 	return 0;
}

代码1正常,代码2在编译的时候会出现连接性错误。

结论:

一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。

11.2.3 修饰函数

//代码1
//add.c
int Add(int x, int y)
{
 	return c+y;
}
//test.c
int main()
{
 	printf("%d\n", Add(2, 3));
 	return 0;
}
//代码2
//add.c
static int Add(int x, int y)
{
 	return c+y;
}
//test.c
int main()
{
 	printf("%d\n", Add(2, 3));
 	 return 0;
}

代码1正常,代码2在编译的时候会出现连接性错误。
结论:

一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。

12. #define 定义常量和宏

//define定义标识符常量
#define MAX 1000
 //define定义宏
#define ADD(x, y) ((x)+(y))
#include <stdio.h>
int main()
{
	int sum = ADD(2, 3);
 	printf("sum = %d\n", sum);
 	sum = 10*ADD(2, 3);
 	printf("sum = %d\n", sum);
 	return 0;
}

引言:接下来的指针以及结构体部分也是C语言中比较重要的部分,在本阶段我们以了解为主,简单介绍。

13. 指针

13.1 内存

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

变量都有地址,取出变量地址如下:

int main()
{
 	int num = 10;
 	&num;//取出num的地址
	printf("%p\n", &num);//打印地址,%p--以地址的形式打印
	return 0;
}

那地址如何存储,需要定义指针变量。

int num = 10;
int *p;//p为一个整形指针变量
p = &num;

以整形指针举例,可以推广到其他类型,如:

#include <stdio.h>
int main()
{
	char ch = 'w';
 	char* pc = &ch;
 	*pc = 'q';
 	printf("%c\n", ch);
 	return 0;
}

13.2 指针变量的大小

#include <stdio.h>
 int main()
 {
 	printf("%d\n", sizeof(char *));
	printf("%d\n", sizeof(short *));
 	printf("%d\n", sizeof(int *));
 	printf("%d\n", sizeof(double *));
 	return 0;
 }

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

14. 结构体

结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含:名字+年龄+性别+学号这几项信息。
这里只能使用结构体来描述了。
例如:

struct Stu
 {
 	char name[20];//名字
	int age;      //年龄
	char sex[5];  //性别
	char id[15]//学号
};

结构体的初始化:

//打印结构体信息
struct Stu s = {"张三"20"男""20180101"};
//.为结构成员访问操作符
printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);
//->操作符
struct Stu *ps = &s;
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps>id);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值