目录
- 前言
- 1. 什么是c语言呢
- 2. 第一个c语言程序
- 2. 数据类型
- 3. 变量和常量
- 3.1 变量
- 3.1.1 变量的定义
- 3.1.2 变量的分类
- 3.1.3 变量的使用
- 3.1.4 变量的作用域和生命周期
- 3.2 常量
- 4. 字符串、转义字符、注释
- 4.1 字符串
- 4.2 转义字符
- 4.3 注释
- 5. 选择语句
- 6. 循环语句
- 7. 函数
- 8. 数组
- 9. 操作符
- 10. 常见关键字
- 11. define定义常量和宏
- 12. 指针
- 13. 结构体
- 后记
前言
大家好,本人最近突发奇想,想要从头学习一下C语言,C生万物,希望从头学完之后整个人会获得巨大升华。于是打算用博客来记录一下学习体会,但我不保证我一定能坚持下去啊,毕竟我这个人,鸽掉了太多东西。之前博主曾经写过一篇总结C语言的文章,是对C语言比较全面的总结,也是目前博主所有文章中数据最好的,大家如果感兴趣可以点击链接阅读一下(C语言–以分号结尾的诗)。博主最近很迷茫,不是最近,是一直很迷茫,觉得不能一直迷茫下去了,也许做一点什么,总比什么也不做好。所以,加油啊。
本系列博客编译器为VS2013.本博客为复习记录,但是会尽力做到细致,对于初学者友好。本人会尽力坚持更新C语言的文章,感谢大家多多支持。
1. 什么是c语言呢
C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
其实也没必要一定知道c语言的准确定义,如果你是一个刚入门的小白的话,其实c语言和英语差不多的道理,你学习英语是为了让老外听懂你说啥,你学习c语言是为了让电脑听懂你说啥。
2. 第一个c语言程序
#include <stdio.h>
int main()
{
printf("Hello world\n");
return 0;
}
这便是大名鼎鼎的计算机祖师爷级别的程序了,当你成功地跑出这个程序的时候,就意味着,你已经一只脚踏入了计科的大门了。
让我们来观察一下这个程序,这个程序虽然简单,但是却包含了一个C语言程序的基本框架。
main函数是程序的入口,代码是从main函数的第一行开始执行的。有且仅有一个。
有一些地方会写成void main()这种形式,但这是一种比较旧的写法。
还有一种主函数的写法是int main(void),还有一种是int main(int argc,char*argv[])这两种写法也都是可以的,在此先不具体展开。
return 0;表示正确返回,是一种约定俗成的传统,事实上换成其他整数也是可以的。
2. 数据类型
我们写代码,就是想要计算机帮我们完成任务,解决问题,这就要求我们的计算机语言能够描述我们现实生活中的问题,这样计算机才知道我们的问题是什么,进而解决。
我们生活中有许多数值,并且这些数值发挥这巨大的作用,于是,如何让计算机读入数值也就十分重要。
在c语言中,这些数据被分为不同的数据类型如下:
至于为什么有这么多的类型,这和计算机内部存储数据的模式有关。数在内存中的存储,我们之后的文章会详细介绍,博主之前的文章也介绍过,大家也可以点击翻看一下(整数在内存中的存储)我们这里就先简单介绍一下。
认识一个操作符:sizeof。它用来计算对应内存的变量所占内存的大小,我们开看一下:
#include <stdio.h>
int main()
{
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));
printf("%d\n", sizeof(long double));
return 0;
}
每种类型的大小就出来啦。这里的数字表示的是字节,也就是说char型数据在内存中占一个字节,以此类推。
那么什么是字节呢?
字节是内存中常见的一个单位。计算机中的单位有,bit-比特,byte-字节,kb,mb,gb,tb,pb……等。
我们知道,计算机是以二进制为基础的。一个二进制的0或1所在计算机内部占的内存就是一个bit,也是计算机中的最小的单位,而一个字节等于8个比特位。1kb=1024个byte,1mb=1024kb,之后都为1024倍了。
这是我们的一个简单介绍。
但是大家可能会发现,int 和long都是4比特位,long是长整型,但是还和整型位数一样的?其实在C语言的标准规定:sizeof(long)>=sizeof(long),所以,只要大于等于就好啦,不一定要大于哦。一个小细节。
还有就是,无论32位还是64位的机器,一个字节都是8个比特位,这是规定,与机器没有关系哦。
我们创造出这么多数据类型,是为了能够表达丰富的数据。在c语言中,我们定义一个数据的写法如下:
int age = 10;
float weight = 45.6f;
char ch = 'c';
这里有几个小细节:
1、我们在定义weight时,45.6后面加了一个f,原因是计算机会认为45.6为double型,会在运行过程中报错,而加上f则会告诉它,这个是float型。
2、我们发现c用‘’了,在C语言中,字符用‘’而“”内是字符串。一个汉字是两个字符哦。
3. 变量和常量
其实在上面,我们就已经涉及到变量的定义了。
什么是变量,什么又是常量呢?在生活中,有一些值是不变的,比如圆周率,身份证号号码,但有些值又是变化的比如身高体重等。在C语言中,不变的值为常量,变地值为变量。
3.1 变量
3.1.1 变量的定义
变量如何定义呢?
int age = 10;
float weight = 45.6f;
char ch = 'c';
3.1.2 变量的分类
放在大括号外部的是全局变量,放在大括号内部的是局部变量。
局部变量和全局变量名字冲突的时候,局部变量优先。
3.1.3 变量的使用
我们来看一个两个数相加的小程序:
#include <stdio.h>
int main()
{
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;
}
3.1.4 变量的作用域和生命周期
作用域
作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的。而限定这个名字的可用性的代码范围就是这个名字的作用域。
- 局部变量的作用域是变量所在的局部范围。
- 全局变量的作用域是整个工程。
生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
1、局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
2、全局变量的生命周期是:整个程序的生命周期。
为了深入探讨生命周期和作用域,我们来看几个例子:
#include<stdio.h>
#include<stdlib.h>
// {}为一个代码块
int main()
{
{
int a = 10;
}
printf("%d\n", a);
}
这个程序是报错的,原因是因为,a是一个局部变量,其作用域仅在定义它的代码块内。这样更改就对啦。
再来看一个例子:
#include<stdio.h>
#include<stdlib.h>
// {}为一个代码块
int main()
{
int b = 100;
{
int a = 10;
printf("%d\n", a);
printf("%d\n", b);
}
printf("%d\n", b);
}
在包含b的代码块内,都可以打印出b。
局部变量的作用域就是自己所在的局部范围。
我们再来感受一下全局变量:
#include<stdio.h>
#include<stdlib.h>
// {}为一个代码块
int a = 10;
void test()
{
printf("a=%d\n", a);
}
int main()
{
{
printf("a=%d\n", a);
}
printf("a=%d\n", a);
test();
}
我们发现每一次打印都成功了,这证明了全局变量的作用域在整个工程。
我们再来看看生命周期:
局部变量的生命周期仅在其局部范围。
全局变量的生命周期在其整个工程。
3.2 常量
常量是不能改变的量。
#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;
}
4. 字符串、转义字符、注释
4.1 字符串
我们来看看这份代码:
#include <stdio.h>
int main()
{
char arr1[] = "ily";
char arr2[] = { 'i', 'l', 'y' };
char arr3[] = { 'i', 'l', 'y', '\0' };
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
}
猜猜输出结果是什么样子的?
为什么是这样呢?
我们知道字符串的结束标志是\0.对于一个字符串,默认结尾是有\0的。在写成数组的形式的时候,要加入\0作为结束标志。如果没有,就会出现arr2那样的情况。
\0本身的值是0,所以最后一个数组放0效果也是一样的。
那么字符串的长度如何计算呢?我们用strlen函数来计算字符串的长度,strlen的库函数是string.h。
#include <stdio.h>
#include<string.h>
int main()
{
char arr1[] = "ily";
char arr2[] = { 'i', 'l', 'y' };
char arr3[] = { 'i', 'l', 'y', 0 };
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));
printf("%d\n", strlen(arr3));
return 0;
}
我们发现,arr2的长度是15,这实际上是一个随机值。
\0是字符串的结束标志,但并不算在字符串长度里。但占内存
4.2 转义字符
转义字符顾名思义就是转变意思。
转义字符 释义
? 在书写连续多个问号时使用,防止他们被解析成三字母词
’ 用于表示字符常量’
\“ 用于表示一个字符串内部的双引号
\ 用于表示一个反斜杠,防止它被解释为一个转义序列符。
\a 警告字符,蜂鸣
\b 退格符
\f 进纸符
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ddd ddd表示1~3个八进制的数字。 如: \130 X
\xdd dd表示2个十六进制数字。 如: \x30 0
我们来看一下这个程序:
#include <stdio.h>
int main()
{
printf("c:\code\test.c\n");
return 0;
}
我们预计屏幕上会打印出来的是c:\code\test.c,而实际上:
为什么会出现这样的结果呢?
因为\t是转义字符水平制表符,也就是我们的tab键,代表8个空格。这就是转义字符的应用。
那么如何才能打印出c:\code\test.c呢?记住一句话“斜杆的作用是使斜杆打印在屏幕上”
#include <stdio.h>
int main()
{
printf("c:\\code\\test.c\\n");
return 0;
}
大家get到斜杆的用法啦嘛?
关于更多的转义字符,就不一一演示啦,大家可以自行解锁探索。
4.3 注释
5. 选择语句
C语言是结构化的程序设计语言。有顺序结构、选择结构、循环结构。
那么什么是选择语句呢?举一个例子:
如果我有一个亿,退学回家躺平。如果我们没有一个亿,好好读书考研搞钱。这就是一个选择。
那么,我们如何通过代码来实现呢?此时此刻,我们的if和else要登场啦。
#include <stdio.h>
int main()
{
int input = 0;
printf("你有一个亿吗?(1/0)?\n");
scanf("%d", &input);
if (input == 1)
printf("退学回家躺平\n");
else
printf("读书考研搞钱\n");
return 0;
}
关于if语句,还有很多具体的小细节,我们就先不在这里详细展开,我们后续会详细介绍,欢迎大家关注我后续的文章。这里只是先给大家基础地介绍一点东西。
6. 循环语句
循环语句,也是我们经常用到的语句。很多事情我们必须要一直重复做,直到一个终点。大家可能看过开端那部电视剧,让循环中止的条件就是阻止爆炸。
C语言中如何实现循环呢?
while语句
for语句
do … while语句
记住,循环语句要有循环中止的条件。否则将会无限循环。
我们来看一下如何利用三种循环语句实现开端中的循环。我们这里只做一下代码演示,以后的博客中会详细介绍。
while
#include <stdio.h>
int main()
{
int input = 0;
int flag = 0;
while (flag == 0)
{
printf("阻止爆炸啦吗?(1/0)?\n");
scanf("%d", &input);
if (input == 1)
{
flag = 1;
printf("循环中止!\n");
}
else
;
}
return 0;
}
for
#include <stdio.h>
int main()
{
int flag = 0;
int input = 0;
for (flag = 0; flag == 0;)
{
printf("阻止爆炸啦吗?(1/0)?\n");
scanf("%d", &input);
if (input == 1)
{
flag = 1;
printf("循环中止!\n");
}
else
;
}
return 0;
}
do while
#include <stdio.h>
int main()
{
int flag = 0;
int input = 0;
do
{
printf("阻止爆炸啦吗?(1/0)?\n");
scanf("%d", &input);
if (input == 1)
{
flag = 1;
printf("循环中止!\n");
}
else
;
} while (flag == 0);
return 0;
}
7. 函数
函数可以简化代码,使代码可以复用
我们举个例子,如果我们要写一个加法程序,不用函数是这样的:
#include <stdio.h>
int main()
{
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 <stdio.h>
int Add(int x, int y)
{
int z = x + y;
return z;
}
int main()
{
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;
}
利用函数,代码看起来更加有条理,并且,如果我们需要进行多个加法时,只要调用函数就好了,可以使代码简洁大气。
8. 数组
数组:一组相同类型元素的结合
数组的定义:
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//定义一个整形数组,最多放10个元素
数组也可以不完全初始化:
nt arr[10] = { 1, 2, 3 };
数组的使用:
#include <stdio.h>
int main()
{
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;
}
注意:数组的下标是从0开始的。
9. 操作符
关于操作符,内容很多,大家可以看我之前的一篇博客。
操作符详解
注意,/得到的是商,%得到的余数。
10. 常见关键字
typedef 顾名思义是类型定义,可用来类型重命名。它的作用是起别名。比如,比如刘备字玄德,刘备是他,玄德也是他。
我们来举一个例子康康:
#include<stdio.h>
typedef int i;
int main()
{
i l = 0;
printf("%d\n", l);
return 0;
}
在上面的例子中,我们给int起了一个别名为i,所以i就可以和int一样使用啦。
我们来看这样一份代码:
#include<stdio.h>
void test()
{
int a = 1;
a++;
printf("%d ", a);
}
int main()
{
int i = 0;
while (i < 10)
{
test();
i++;
}
return 0;
}
输出的结果是这个样子的:
因为a是局部变量,每一次调用完之后都会销毁。但是如果我们将代码进行一下小小的改动。
#include<stdio.h>
void test()
{
static int a = 1;
a++;
printf("%d ", a);
}
int main()
{
int i = 0;
while (i < 10)
{
test();
i++;
}
return 0;
}
输出结果就变成这样子的了。
static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。所以这次打印出来的是2到11.
如果static修饰全局变量:
如果static修饰函数:
register是建议把自己创建的变量存储到寄存器中。寄存器变量不能取地址。
11. define定义常量和宏
定义常量:
//define定义标识符常量
#define MAX 1000
定义宏:
#include <stdio.h>
//define定义宏
#define ADD(x, y) ((x)+(y))
int main()
{
int sum = ADD(2, 3);
printf("sum = %d\n", sum);
sum = 10 * ADD(2, 3);
printf("sum = %d\n", sum);
return 0;
}
define定义宏没有类型检查。
关于宏还有很多具体的小细节,欢迎大家关注我之后的文章。
12. 指针
指针,一个好东西,一个让人凌乱的好东西。一个让人懵逼的好东西。指针,痛啊,真痛啊。
内存空间是如何管理的呢?
内存的使用管理是效仿了生活中对于空间的管理。比如一个小区,分为许多栋楼,然后每一栋楼又有很多层,每一层又住了许多户人家。我们的内存也是,划分了很多小的内存单元。
内存是电脑上特别重要的存储器,计算机中所有程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
变量都有地址,我们可以取变量的地址:
#include<stdio.h>
int main()
{
int num = 10;
#//取出num的地址
printf("%p\n", &num);//打印地址,%p--以地址的形式打印
return 0;
}
我们了解了地址,那么地址又如何储存呢?噔噔蹬蹬,指针闪亮登场。指针是存储地址的变量。
#include<stdio.h>
int main()
{
int a = 10;
int *pa = &a;//pa是专门用来存放地址的,pa叫指针变量。
//*说明pa是指针变量,int说明pa指向的是整型变量。
return 0;
}
指针大小在32位平台是4个字节,64位平台是8个字节。
关于指针,有许多具体而丰富的细节,我们后续会详细介绍。
13. 结构体
我们之前介绍过数据类型,但是现实世界是复杂的,那些类型很难描述出复杂的现实世界。
于是,结构体登场,用以描述复杂的情况。
比如,我们描述一个学生,他包含着很多信息。比如名字、年龄、性别、学号等等,这时,我们就可以这样描述。
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);
后记
我们初识C语言部分就到这里了。之后如果我足够勤奋的话,我会继续更新后面的内容。希望我不要懒惰。
我是一个在学业上很失败的大学生,无数次想要奋发图强又无数次放弃。所以很希望自己,能够做到彻底地坚持。
加油加油。大家都加油。