经典灵魂三问:
- 什么是C语言?
- 为什么要学C语言?
- 怎样学好C语言?
C语言是一种面向过程的高级语言,广泛应用于底层开发。
面向过程:简单来说就是分析出解决问题所需要的步骤,然后按照步骤一步步编程实现。面向过程以实现功能的函数为主,如果需要实现某个功能,只需要编写对应的函数即可。
可能很多友友们都会说我是被迫的,是学校要求的(我第一次接触C语言也是这样emmm),从入门到放弃。
但是一码归一码,学好C语言真香。
近 50 年内,在 TIOBE 排行榜中, C语言一直霸占前三名,没有丝毫撼动,可谓经典永不过时!
当然,学好了C语言薪资肯定不是问题,虽然现在互联网的行情不太乐观,但是留得青山在,不怕没材烧,只要有过人的技术,还是香饽饽。
【现状】大部分大学课程都是应试教育,并且使用的教材早过了,老师也跟不上社会的发展,导致大部分学生根本达不到公司的要求,所以我们为了未来的好offer必须啃掉这些硬骨头啊,一起加油吧!
注意:
注意: 这一章所有的内容都是点到为止,目的是为了让大家了解C语言的整体框架,先整体切入,后详细剖析,步步为营,循序渐进,跟着笔者一起进步把。
#include
int main(void)
{
printf("hello world");
return 0;
}
注:main()函数有且只有一个,是程序的入口。
//基本数据类型
char //字符数据类型
short //短整型
int //整形
long //长整型
float //单精度浮点数
double //双精度浮点数
#include
int main(void)
{
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;
}
//注意:C语言没有明确规定long的大小,只要不小于int类型就行了
注:存在这么多的类型,其实是为了更加丰富的表达生活中的各种值。
sizeof()是一种操作符,用来计算运算对象所占空间大小,单位是字节。
当然,用%zu打印更好,用来打印无符号整型,%d打印十进制整数。
C语言规定,sizeof返回size_t类型的值,即无符号整型
类型的使用
int weight = 100;
char ch = 'a';
double price = 123.3;
生活中有些值是恒定不变的(例如:圆周率,身份证号码,血型等)统称为常量。
有些值是可以变的(例如:身高,体重,价格等)统称为变量。
声明变量
基本类型+变量名;
int age;
int cows,goats;
初始化变量
初始化(initialize)变量就是为变量赋一个初始值。当然初始化可以直接在声明中完成。
int age = 150;
int cows = 32, goats = 14;
double price = 100.25;
_
)组成。#include
int global = 2022;//全局变量
int main(void)
{
int local = 2021;//局部变量
//下面定义的global会不会有问题?
int global = 2020;//局部变量
printf("global = %d\n", global);//2020
return 0;
}
总结:
上面的局部变量global变量的定义没有问题。
当局部变量和全局变量同名的时候,局部变量优先使用。
#include
int main(void)
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = num1 + num2;
printf("sum = %d\n", sum);
return 0;
}
scanf() 输入 - - 如果用scanf()读取基本变量类型的值,在变量名前加上一个
&(取地址符号)
printf() 输出/打印
作用域
作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
生命周期
变量的生命周期是指的是变量的创建到变量的销毁之间的一个时间段。
C语言中的常量分为以下几种:
const
修饰的常变量#include
//#define的标识符常量
#define MAX 100
//枚举常量
enum Sex
{
//下面是enum Sex类型变量的可能取值,这三个可能取值就是枚举常量
MALE,
FEMALE,
SECRET
};
int main(void)
{
//字面常量 3.14 1000
//const 修饰的常变量
const float pai = 3.14f;//pai是const的修饰的常变量
//pai = 33.4;//error 不能直接修改
//#define的标识符常量 演示
printf("max = %d\n", MAX);
//枚举常量演示
printf("%d\n", MALE);//0
printf("%d\n", FEMALE);//1
printf("%d\n", SECRET);//2
//注:枚举常量的默认是从0开始,依次向下递增1
return 0;
}
注:
上面例子上的
pai
被称为const
修饰的常变量,const
修饰的常变量在C语言中只是在语法层面限制了变量pai
不能直接被改变,
即:const
关键字用于限定一个变量为只读。
但是pai
本质上还是一个变量,所以叫常变量。
"hello world.\n"
这种由双引号引起来的一串字符称为字符串字面值,简称字符串
注:字符串的结束标志是一个\0
的转义字符。在计算字符串长度的时候\0
是结束标志,不算作字符串的内容。
#include
int main(void)
{
char arr1[] = "abc";
char arr2[] = {'a', 'b', 'c'};
char arr3[] = {'a', 'b', 'c', '\0'};
//string length
//strlen是库函数,是专门求字符串长的函数
printf("%d\n", strlen(arr1));//3
printf("%d\n", strlen(arr2));//随机数,arr2中没有'\0'
//printf("%s\n", arr1); //abc
//printf("%s\n", arr2); //abc烫烫烫(乱码)
return 0;
}
//%s 是打印字符串,遇到\0打印自然结束
假如我们要在屏幕上打印一个目录:c:\code\test.c
我们该如何实现代码呢?
#include
int main(void)
{
printf("c:\code\test.c\n");
return 0;
}
实际上运行结果是这样:
为什么会这样呢?
这里就不得不提转义字符了,转义字符顾名思义就是转变的意思。
转义字符 | 释义 |
---|---|
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
\’ | 用于表示字符常量 |
\" | 用于表示一个字符串内部的双引号 |
\\ | 用于表示一个反斜杠,防止它被解释为一个转义序列符 |
\a | 警告字符、蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制的数字。如: \130 表示 X |
\xdd | dd表示2个十六进制的数字。 如:\x30 表示 0 |
下面来介绍一下\ddd
和\xdd
补充:
二进制:由0和1组成的 例如:00001010
八进制组成:0 1 2 3 4 5 6 7
十进制组成:0 1 2 3 4 5 6 7 8 9 10
十六进制组成:0 1 2 3 4 5 6 7 8 9 A B C D E F
进制转换:
二进制数的值转换成十进制数的值,只需将二进制数的各数位的值和位权相乘,然后将相乘的结果相加即可。
\ddd
是一个转义字符,ddd表示1~3个八进制数字,\ddd
就是把ddd这个8进制数转成10进制数字,然后找到这个十进制数字对应的ASCII码值,即为转义的值。\xdd
, dd表示两个十六进制数字,如\x30 , '\xdd’中的\x后面跟的数字默认的是十六进制的。了解了转义字符后,就可以修改上述代码了
#include
int main(void)
{
printf("c:\\code\\test.c\n");//只用在转义字符前加上\就行了
return 0;
}
就浅浅的来两个小问题热热身吧
问题1:在屏幕上打印一个单引号’怎么做?
问题2:在屏幕上打印一个字符串,字符串的内容是一个双引号",怎么做?
#include
int main(void)
{
//
printf("%c\n", '\'');//打印一个单引号'
printf("%s\n", "\"");//打印一个双引号"
}
笔试题:
//程序输出了什么?
#include
int main(void)
{
printf("%d\n", strlen("abcdef"));
//\62被解析成一个转义字符
printf("%d\n", strlen("c:\test\628\test.c"));
return 0;
}//6 14
strlen是库函数,求字符串长度,即
\0
之前的字符个数。
#include
int Add(int x, int y)
{
return x + y;
}
/*
int Sub(int x, int y)
{
return x - y;
}
*/
int main(void)
{
//C++注释风格
//int a = 10;
//调用Add函数,实现加法
printf("%d\n", Add(1, 2));
return 0;
}
注释有两种风格:
/*xxxxxxxxx*/
//xxxxxxxxx
俗话说的好一个正确的选择胜过千百次的努力。
#include
int main(void)
{
int coding = 0;
printf("C语言你学废了吗? (选择1 or 0):>");
scanf("%d", &coding);
if (coding == 1)
{
printf("接着烤红薯吧\n");
}
else
{
printf("腾讯还差一个你\n");
}
return 0;
}
有些事情一直重复做,比如我们日复一日的学习,日复一日的摆烂(开玩笑)。
C语言中循环如何实现呢?
#include
int main(void)
{
printf("关注笔者\n");
int line = 0;
while (line <= 200)
{
line++;
printf("我要努力敲代码\n");
}
if (line > 200)
{
printf("好offer\n");
}
return 0;
}
当然,如果你真的想要拿到好offer至少得敲20000行有效代码,和几个拿得出手的好项目。
#include
int main(void)
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("请输入两个操作数:>");
scanf("%d%d", &num1, &num2);
sum = num1 + num2;
printf("sum = %d\n", sum);
return 0;
}
//将上述代码写成函数
//如下
#include
int Add(int x, int y)
{
int s = x + y;
return s;
}
int main(void)
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("请输入两个操作数:>");
scanf("%d%d", &num1, &num2);
sum = Add(num1, num2);
printf("sum = %d\n", sum);
return 0;
}
函数的特点就是简化代码,代码复用。(以后的章节会细说,敬请期待 ^ - ^)
如果要存储1-10的数字,该怎么存储?
C语言中给出了数组的定义:一组相同类型元素的集合
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整型数组,最多放10个元素
C语言规定:数组的每个元素都有一个下标,下标是从0开始的。
数组可以通过下标来访问。
例如:
in arr[10] = {0};
//如果数组10个元素,下标的范围是0~9
#include
int main(void)
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
简单介绍,后面会重点讲解
算术操作符
+ - * / %
移位操作符
>> <<
位操作符
& ^ |
赋值操作符
= += -= *= /= &= ^= |= >>= <<=
单目操作符
(只有一个操作数的操作符就叫单目操作符)
! 逻辑反操作符
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
补充:
strlen
是库函数
strlen
是求字符串长度的,关注是字符串中是否有\0, 统计\0之前的字符个数。
sizeof
是操作数
sizeof
只关注占据了多大的内存空间,不关注内存中存放的数据。单位是字节
char arr1[] = "abc";
arr1是由'a' 'b' 'c' '\0' 组成
char arr2[] = {'a', 'b', 'c'};
其中不包括'\0'
"abc" 是字符串
'a' 是字符
关系操作符
>
>=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”
逻辑操作符
&& 逻辑与
|| 逻辑或
条件操作符(三目操作符)
exp1?exp2:exp3
逗号表达式
exp1,exp2,exp3, ...expN
下标引用、函数调用和结构成员
[] () . ->
auto break case char const continue default do double
else enum float for int long register return short
extern sizeof static struct switch typedef union void while
C语言提供了丰富的关键字,这些关键字都是语言本身预先设定好的,用户自己是不能创造关键字的。
#include
//define 定义标识符常量
#define MAX 100
//define 定义宏
#define ADD(x,y) x+y
int main(void)
{
int sum = ADD(2, 3);
printf("sum = %d\n", sum);//5
sum = 10 * ADD(2, 3);
printf("sum = %d\n", sum);//23
return 0;
}
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的。
所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。
为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
内存单元编号 --> 地址 --> 指针
变量是创建在内存中的(在内存中分配空间),每个内存单元都有地址,所以变量也是由地址的。
取出变量的地址如下:
#include
int main(void)
{
int num = 10;//num向内存申请4个字节空间
#//取出num的地址
//注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)
printf("%p\n", &num);//打印地址,%p是以地址的形式打印
return 0;
}
那地址如何存储,需要定义指针变量。
int num = 10;
int *p;//p为一个整型指针变量
p = #
指针的使用实例:
#include
int main(void)
{
int num = 20;
int* p = #
*p = 10;
printf("%d\n", num);
return 0;
}
#include
int main(void)
{
char ch = 'w';
char* pc = &ch;
*pc = 'a';
printf("%c\n", ch);//a
return 0;
}
#include
int main(void)
{
printf("%d\n", sizeof(char*));
printf("%d\n", sizeof(short*));
printf("%d\n", sizeof(int*));
printf("%d\n", sizeof(double*));
return 0;
}
指针变量的大小取决于地址的大小
32位平台下地址是32个bit位(即4个字节)
64位平台下地址是64个bit位(即8个字节)
结论: 指针大小在32位平台是4个字节,64位平台是8个字节。
结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含:姓名+年龄+性别+学号
这几项信息。
这里就只能使用结构体来描述了。
例如:
#include
struct Stu
{
char name[20];
int age;
char sex[5];
char id[15];
};
int main(void)
{
//结构体的初始化
struct Stu s = { "张三", 20, "男", "20220101" };
//结构体成员访问
//.操作符为结构体成员访问操作符
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);
return 0;
}
注意:
上述仅仅是对C语言的一个简单概述,后术笔者会详细讲解判断循环语句、数组、指针、操作符、结构体等等,为了防止走散,还请大家活动下双手,给俺来个一键三连,感谢各位老铁的支持!!!
小红花走一波~~~