本文主要是介绍C语言初印象(1.2w字粗略讲讲C),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
PS
计算机语言
浅谈语言 - 与自然语言的区别
发展历程
C语言简述
c语言的国际标准
c语言的常用编译器
源文件和头文件
内存单位以及转换
C语言的数据类型
第一个c语言程序
在屏幕上打印hello world!
运行结果
代码分析
转义字符表
\n
\\和\t
\'和\"
\ddd
进制转换
ASCⅡ码表
\xdd
字符串
\0
常量与变量
定义变量的方法(变量的初始化)
已定义变量的再赋值
变量命名的注意事项
变量的分类
这里为大家列出输入输出(% + 字符)格式及意义
变量使用
变量的作用域和生命周期
作用域
生命周期
常量
字面常量
const 修饰的常变量(这个本质上属于变量,只是拥有常量的属性)
#define的标识符常量
枚举常量
注释
注释有两种风格:
C语言风格的注释
C++风格的注释(建议使用这个)
选择语句(分支语句)
分类:
if分支语句模板
循环语句
分类:
while循环模板
函数
函数定义的模板
数组
数组的定义模板
数组的下标
数据的使用
操作符
算术操作符
/(除号)
% (取模)
移位操作符
位操作符
赋值操作符
单目操作符(后接上一个操作数)
!
sizeof(用来计算数据类型、变量的大小,计算出来的结果单位是字节byte)
sizeof和strlen的区别
++,--
关系操作符
逻辑操作符
三目操作符
逗号表达式
下标引用、函数调用和结构成员
常见关键字
extern
typedef
static
修饰局部变量
修饰全局变量
修饰函数
#define 定义常量和宏
define定义常量模板
define定义宏
内存
指针变量模板
指针变量的大小
结构体
结构体模板
结构体变量
写在最后
PS
本文是对C语言进行一个大概的描述!!!对相应的知识点并不进行详细的说明和记录,换句话说就是点到为止,讲点武德!详细知识点可见后续已更blog。
计算机语言
浅谈语言 - 与自然语言的区别
自然语言 - 人与人交流的语言 (汉语、英语等)
计算机语言 - 人与计算机交流的语言(c/c++/python等)
发展历程
首先是一开始计算机科学家运用的机械语言,也就是二进制语言,也就是由0和1组成的一串数字。
可以直接被计算机识别,不用进行编译。
接着就是汇编语言 由ADD SUB等助记符组成的语言。
然后就是B语言。
紧接着,我们如今比较常用的一些高级计算机语言,比如 c / c++ /python。
纵观整个计算机语言发展过程,语言都是逐渐地由低级变为高级。
语言也越来越接近我们的自然语言。便于我们人和人之间理解和沟通。
C语言简述
C语言是一种高级的计算机语言,广泛应用于底层开发。
说到底层不得不提到这张图(拿JAVA和c举例)(分割线往下是底层)
c语言的国际标准
就像国际基本单位一样,在国际单位制中,将单位分成三类:基本单位、导出单位和辅助单位。 7个严格定义的基本单位是:长度(米)、质量(千克)、时间(秒)、电流(安培)、热力学温度(开尔文)、物质的量(摩尔)和发光强度(坎德拉)。有了这些标准,我们人类社会的科学发展才得以顺利进步。
一个好的计算机语言必须有国际标准,这样才便于这种语言的传播,普及,以及程序员之间的合作和交流。目前C语言比较普及的国际标准是C89和C90。
c语言的常用编译器
编译器是将高级计算机语言转换为二进制语言的工具。
C语言的常见编译器:Clang、GCC、MSVC等。
源文件和头文件
.c 后缀的是c的源文件,.h 后缀是头文件。
内存单位以及转换
一个bit位可以存储一个二进制的数字(一个0或者1)。
C语言的数据类型
浮点数也就是小数。
整型就是整数。
有如此多数据类型是因为每种数据类型占用计算机的内存不一样,所以可以达到节约内存空间的效果。
具体数据类型所占内存空间如下表(仅供参考,不同的编译环境有可能不同)
数据类型 | 所占内存(单位:byte) |
char | 1 |
short | 2 |
int | 4 |
long | 4 |
long long | 8 |
float | 4 |
double | 8 |
c语言规定 long 的所占内存 >= int 的所占内存。
第一个c语言程序
在屏幕上打印hello world!
#include <stdio.h>
int main()
{printf("hello world!\n");return 0;
}
运行结果
代码分析
#include <stdio.h>
#开头的是预处理指令。
这个语句是引用头文件,stdio是standard input output(标准输入输出)英文缩写。
c语言的标准输出函数 就是 printf(), 标准输入函数 就是 scanf() ,如果需要运用到这两个函数必须引用头文件stdio.h。
main是主函数,在一个项目中必须有且仅有一个。
{}花括号里面的是函数内容。
一个函数的模板
返回值类型 函数名(函数参数)
{函数内容
return 返回值;
}
根据这个模板,我们大概能知道,main前面的 int 是函数返回值类型。
return 0;
return后面接与函数返回值类型对应的数值,main 函数 一般的函数返回值类型是int ,返回值 一般是0,非0一般表示程序出错。
即main函数建议这样写
int main()
{//内容return 0;
}
main不建议的写法
void main
{//这种写法非常古老
}
\n是转义字符的一种,意思是换行。(转义字符一般来说不显示在程序的输出结果)
转义字符表
转义字符 | 释义 |
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
\' | 用于表示字符常量' |
\“ | 用于表示一个字符串内部的双引号 |
\\ | 用于表示一个反斜杠,防止它被解释为一个转义序列符。 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 禁止符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制的数字。 如: \130 X |
\xdd | dd表示2个十六进制数字。 如: \x30 0 |
\0 | 字符串结束标志 |
\n
比方说我们将\n放在hello world!的中间看看是否会换行
#include <stdio.h>
int main()
{printf("hello \n world!");return 0;
}
运行结果
很明显可以看到这句话是被\n换行了的。
\\和\t
假设我们需要在屏幕上打印一个目录D:\test.c
#include <stdio.h>
int main()
{printf("D:\test.c\n");return 0;
}
运行结果
可以看到输出结果并没有和我们想的那样是D:\test.c。
为什么呢?因为\和t结合形成一个转义字符\t,其作用是在屏幕上打印一个大空格(TAB键按出的大空格)
那么想要正确的输出D:\test.c,必须在\前面再加上一个\形成一个转义字符\\,其作用是输出一个\。
#include <stdio.h>
int main()
{printf("D:\\test.c\n");return 0;
}
运行结果
\'和\"
如何在屏幕上输出一个'和"呢?
代码如下
#include <stdio.h>
int main()
{//问题1:在屏幕上打印一个单引号',怎么做?//问题2:在屏幕上打印一个字符串,字符串的内容是一个双引号“,怎么做?printf("%c\n", '\'');printf("%s\n", "\"");return 0;
}
\ddd
\ddd表示1~3个八进制数字 也就说可以有 \d ,\dd,\ddd。
可以看到\130是八进制下的130转换为十进制是88,那为什么\130对应字符X呢?
首先我们先一个一个来,先看看八进制下130如何转换为十进制下88
进制转换
十进制下123为什么就是123呢?
这就要说到权重问题了
个位对应的权重是,十位对应的权重是,百位对应的权重是。
所以十进制下123就是1*+2*+3*=123(十进制)。
八进制下130 = 1*+3*+0*= 88(十进制)。
由此可知
n进制的权重就是n的k次幂,k由位数决定。
那为什么十进制的88对应字母X呢?这就要讲到ASCⅡ码表了
ASCⅡ码表
字母还有一些符号都可以转变为十进制数字,而十进制数字又可以转变为二进制数字,便于计算机储存这些字母和符号。
由表可以知道,X对应88。
\xdd
\xdd 中 dd表示2个16进制数字 16进制 和 8进制的差别就在\后面是否有x
可以看见\x30对应十进制数字48,又对应字符0(零)。
字符串
"hello world!"
这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
\0
字符串结束符号,输出时计算机找到该符号表示输出的字符串到此结束。
我们用字符数组存放字符串
#include <stdio.h>
//下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
{char arr1[] = "abc";//双引号引起来的字符串自带\0char arr2[] = { 'a', 'b', 'c' };char arr3[] = { 'a', 'b', 'c', '\0' };printf("%s\n", arr1);printf("%s\n", arr2);printf("%s\n", arr3);return 0;
}
运行结果
我们可以看到arr1因为是用双引号初始化的,所以本身自带\0字符串结束符,所以输出结果正常。
arr2和arr3都是字符数组单个单个元素初始化,唯一不同就是arr3有\0,arr2没有。
所以arr2输出结果不正常,arr3输出结果正常。
无论如何输出字符串都需要找到\0,才算作输出字符串的结束。arr2没有\0,所以输出乱码。
常量与变量
定义变量的方法(变量的初始化)
变量定义模板
数据类型 变量名 = 变量值;
int age = 20;
float weight = 45.5;
char ch = 'w';
已定义变量的再赋值
对于一个已定义的变量是可以修改它的数值的!
比如下面这样,我先对变量age初始化为20,后面我可以用下面这个模板把age变量赋值为18.
已定义变量的再赋值模板
已定义变量 = 数值;
int age = 20;//初始化变量age
age = 18;//已定义变量的再赋值
变量命名的注意事项
变量的分类
#include <stdio.h>
int a = 2019;//全局变量
int main()
{int local = 2018;//局部变量//下面定义的a会不会有问题?int a = 2020;//局部变量printf("a = %d\n", a);return 0; }
运行结果
可以看见如果有一个全局变量和局部变量名字相同时,引用时优先使用局部变量。(不建议变量重名)
printf函数里面的%d是将变量值变成十进制数输出。
用scanf 和 printf 输入输出变量值,只能通过%+字符的形式进行。
这里为大家列出输入输出(% + 字符)格式及意义
% + 字符 | 意义 |
%d | 十进制整数 |
%ld | 更大精度的十进制整数 |
%u | 无符号的整数 |
%c | 一个字符 |
%s | 一个字符串 |
%f | 浮点数 |
%lf | 更大精度的浮点数 |
%o | 八进制整数 |
%x | 十六进制整数 |
%e | 指数 |
变量使用
#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; }
这里需要注意的是scanf函数中引用的变量需要在变量前面加上取地址符号(&)。
%+字符一定要和变量一一对应上,如果有多个变量用逗号隔开。
一定要注意的是scanf函数里面不能有\n转义字符。
变量的作用域和生命周期
作用域
作用域( scope )是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效 可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
常量
C语言中的常量分为以下以下几种:
字面常量
#include <stdio.h>
int main()
{//字面常量3.14;//浮点数常量2000;//整型常量'c';//字符常量"hello";//字符串常量printf("%f\n", 3.14);printf("%d\n", 2000);printf("%c\n", 'c');printf("%s\n", "hello");return 0;
}
const 修饰的常变量(这个本质上属于变量,只是拥有常量的属性)
它与一般变量最大的不同就是,const 修饰的常变量不能进行再赋值操作。
在初始化数组时,它不能作为数组元素的个数去定义数组,所以它是变量。
#define的标识符常量
枚举常量
修改第一个枚举常量后的结果
不论哪种常量都不可以进行再赋值操作,有一些常量需要初始化。
注释
#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
选择语句(分支语句)
分类:
if分支语句模板
//选择语句、分支语句,每个分支都有前提条件,
//符合前提条件进入分支,执行分支内容。
//判断前提条件时,从上往下判断。
//当你列出的前提条件都不满足时,进入else分支。
if (前提条件)
{
//该分支内容
}
else if (前提条件)
{
//该分支内容
}
//...
else
{
//该分支内容
}
第一个分支语句必须是if语句,后面带小括号(),小括号里面是前提条件,后面接花括号{},括号是分支内容。
接下来的语句就是else if语句,后面带小括号(),小括号里面是前提条件,后面接花括号{},括号是分支内容。(else if 语句 可缺省)
最后就是else语句,没有小括号和前提条件,后面接花括号{},括号是分支内容。(else 语句 可缺省)
例子:
#include <stdio.h>
int main()
{int coding = 0;printf("你会去敲代码吗?(选择1 or 0):>");scanf("%d", &coding);if(coding == 1){printf("坚持,你会有好offer\n");}else{printf("放弃,回家卖红薯\n");}return 0; }
结果:
循环语句
有一些东西是需要我们坚持的,比如敲代码和学习。
分类:
1.while语句
2.for语句(后面blog会详细讲,浅浅地提一下)
3.do while语句(后面blog会详细讲,浅浅地提一下)
while循环模板
先判断是否符合前提条件,符合就循环一次,每次进入循环前,都需要进行判断直到不符合条件为止
while ( 前提条件 )
{
//循环内容
}
while语句实例
#include <stdio.h>
int main()
{int line = 0;while(line<=20000){line++;printf("我要继续努力敲代码\n");}if(line>20000)printf("好offer\n");return 0;
}
注意: line++; 相当于 line = line + 1; 。
函数
函数定义的模板
返回值类型 函数名(函数参数)
{函数内容
return 返回值;
}
比如我们想让两个整型num1和num2相加赋值给sum,那我们就要写这个语句。
sum = num1 + num2;
完整代码:
#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);//函数调用,函数返回值赋值给sumprintf("sum = %d\n", sum);return 0;
}
函数可以简化程序,达到代码重复使用的效果。
数组
数组的定义模板
数据类型 数组名 [数组中元素个数] = { 初始化内容多个元素初始化用逗号隔开 };
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素
数组的下标
int arr[10] = {0};
//如果数组10个元素,下标的范围是0-9
数据的使用
#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; }
运行结果
操作符
算术操作符
+(加) -(减) *(乘) /(除) %(模)
+,-,* 没什么好说的。
/(除号)
如果是两个整型相除,比如7/2,结果并不是3.5,而是3。
因为整型和整型相除只能得到整型,想让除出来的数是小数(浮点数),必须将其中一个数变成浮点数,比如 7.0/2 或者 7/2.0 最后得出的结果才是 3.5 。
% (取模)
如果两个数取模得到的是他们的相除后得到余数。比如 7%2 得到 1。
移位操作符
<< (左移) >> (右移)
位操作符
&(按位与) ^(按位异或) |(按位或)
赋值操作符
= += -= *= /= &= ^= |= >>= <<=
单目操作符(后接上一个操作数)
! 逻辑反操作- 负值+ 正值& 取地址sizeof 操作数的类型长度(以字节为单位)~ 对一个数的二进制按位取反-- 前置、后置--++ 前置、后置++* 间接访问操作符(解引用操作符)(类型) 强制类型转换
!
C语言中 0表示假 非0表示真。
//情况1
a = 0;
!a = 1;//情况2
a = -1;
!a = 0;
sizeof(用来计算数据类型、变量的大小,计算出来的结果单位是字节byte)
#include <stdio.h>
int main()
{printf("%d\n", sizeof(int));return 0;
}
sizeof不是函数,是操作符。
sizeof计算数组时,如果括号里放数组名字,算得的是数组的总大小;
括号如果放数组元素,计算的是数组元素的大小。
sizeof和strlen的区别
strlen 是库函数
strlen 是求字符串长度的,关注字符串中是否有\0,统计\0之前的出现的字符个数。
sizeof是操作符
sizeof只关注占据了多大的内存空间,不关注内存中存放的内容。
sizeof的返回值单位是字节。
++,--
有两种用法前置++,和后置++。
//如果是像这样单独语句,前置和后置没有区别a++;//后置,相当于a = a + 1;
++a;//前置,相当于a = a + 1;a--;//后置,相当于a = a - 1;
--a;//前置,相当于a = a - 1;//如果嵌套在其他语句中,有区别。前置先计算,再使用。后置先使用,再计算。//情况1 前置
int a = 0;
printf("%d\n", ++a);//结果为1
printf("%d\n", a);//结果为1//情况2 后置
int a = 0;
printf("%d\n", a++);//结果为0
printf("%d\n", a);//结果为1
关系操作符
> 大于>= 大于等于< 小于<= 小于等于!= 不相等== 相等
逻辑操作符
&& 逻辑与|| 逻辑或
三目操作符
? : ;
条件判断? 条件为真的执行内容 : 条件为假的执行内容 ;
例子
m = a > b ? a : b;
如果a>b成立,a就会赋值给m;不成立b赋值给m。
逗号表达式
exp1 , exp2 , exp3 , …expN
下标引用、函数调用和结构成员
[] ----下标引用 () ------ 函数调用 . ------ 结构成员 -> ------- 结构成员
常见关键字
auto break case char const continue default do double else enumextern float for goto if int long register return short signedsizeof static struct switch typedef union unsigned void volatile while
extern
可以将函数和变量在同一个项目内跨文件使用。
//test1111.c中的代码
int a = 1000;//test.c中的代码
#include <stdio.h>
extern a;
int main()
{printf("%d\n", a);//结果是1000
}
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; }
static
在C语言中:static是用来修饰变量和函数的1. 修饰局部变量-称为静态局部变量2. 修饰全局变量-称为静态全局变量3. 修饰函数-称为静态函数
修饰局部变量
结论:
static修饰局部变量改变了变量的生命周期
让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。
修饰全局变量
//代码1
//test1111.c中的代码
int a = 1000;//test.c中的代码
#include <stdio.h>
extern a;
int main()
{printf("%d\n", a);//结果是1000
}
//代码2
//test1111.c中的代码
static int a = 1000;//test.c中的代码
#include <stdio.h>
extern a;
int main()
{printf("%d\n", a);//编译出错
}
一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。
修饰函数
//代码1
//test1111.c中的代码
int Add(int x, int y)
{return x + y;
}//test.c中的代码
#include <stdio.h>
extern Add(int,int);
int main()
{printf("%d\n", Add(2, 3));//结果是5return 0;
}
//代码2
//test1111.c中的代码
static int Add(int x, int y)
{return x + y;
}//test.c中的代码
#include <stdio.h>
extern Add(int,int);
int main()
{printf("%d\n", Add(2, 3));//编译出错return 0;
}
一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。
#define 定义常量和宏
#include #define 预处理指令
define定义常量模板
#define 常量名字 数值
define定义宏
宏是有参数的,和函数很像。
例子
#define ADD(x, y) ((x) + (y))
宏的参数没有数据类型,用宏是一定需要用括号,避免出错。
宏的本质是替换,函数是调用。
内存
为有效使用内存空间,把内存划分为一个个小的内存单元。(一个内存单元的大小是一个字节。)
类似于把一栋楼划分为一户户人家。而每个地址都有储存有一个数值。
如果把计算机的内存比作一栋楼的话,每一个内存单元都相当于一户人家,而每户人家都有编号,内存单元的编号就称为地址,而每户人家里面的人,就相当于存放的数值。
32位机器有32位地址线,状态(1/0)。
可以管理2的32次个内存单元。所以32位机器可以管理 2的32次byte == 4gb的内存空间。
编号 == 地址 == 指针 。
#include <stdio.h>
int main()
{ int num = 10;#//取出num的地址//注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)printf("%p\n", &num);//打印地址,%p是以地址的形式打印return 0;
}
对于占多个内存单元的变量,取该变量的地址,是取该变量的首地址。取内存单元的个数由变量的数据类型决定。
那地址如何存储,需要定义指针变量。指针变量可以用来储存地址。
指针变量模板
对应变量数据类型 * 指针变量名 = &对应变量
*说明是指针变量。
1.指针本质是地址。
2.口头语中,说的 “指针” 是 “指针变量”。
指针变量用来存对应变量的首地址,根据其数据类型可以找到对应变量。
int num = 10;
int *p;//p为一个整型指针变量
p = #//p指向num
指针的使用实例:
#include <stdio.h>
int main()
{int num = 10;int *p = #*p = 20;//相当于 num = 20;return 0;
}
以整形指针举例,可以推广到其他类型,如:
#include <stdio.h>
int main()
{char ch = 'w';char* pc = &ch;*pc = 'q';printf("%c\n", ch);return 0;
}
指针变量的大小
#include <stdio.h>
//指针变量的大小取决于地址的大小
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{printf("%zu\n", sizeof(char *));printf("%zu\n", sizeof(short *));printf("%zu\n", sizeof(int *));printf("%zu\n", sizeof(double *));return 0;
}
指针大小在 32 位平台是 4 个字节,64位平台是 8 个字节。
结构体
结构体模板
struct 结构体名字
{
//结构体成员
//描述结构体的相关数据
};
结构体变量
struct 结构体名字 结构体变量 //结构体变量的定义
结构体变量.结构体成员 //访问成员
结构体指针变量->结构体成员 //访问成员
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语言初印象(1.2w字粗略讲讲C)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!