C语言是一门通用计算机编程语言,广泛应用于底层开发。
C语言的目标是提供一种比较简易的方式进行编译的编程语言, 尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可以在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)。
C语言历史:二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制 定了一套完整的美国国家标准语 法,称为ANSI C,作为C语言最初的标准。后来又国际标准化组织(ISO)和国际电工委员会(IEC)发布C11,再后来的C99成为截至目前的C语言最新标准,,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。
和其他编程语言的区别:C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。
主要编译器:Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等
#include //引用头文件,使我们可以使用C语言库本身提供函数,即库函数(被封包好的函数,具体实现无法看到,可以从msdn查内部原理)
int main()//main()是主函数
{
printf("hello world\n");//printf()是输出函数,转义字符'\n'是换行的意思
return 0;//使程序退出,0的意思是程序正常退出
}
//解释:
//main函数是程序的入口
//一个工程中main函数有且仅有一个
char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度浮点数
C语言有没有字符串类型:
答案**:C语言本身没有字符串类型,在c语言程序中使用的字符串实际是字符数组(由多个字符组成)**
字符串的两种定义方式:#include
int main() { char string1[] = "abc"; char string2[] = { 'a','b','c' }; return 0; } 两种定义方式的区别:
- 为什么要有这么多种数据类型?
一方面是能够存储更加多样的数据,便于进行数据处理
另一方面的原因就是为了能够更好节约我们的内存空间
- 每种数据类型的大小是多少?
利用sizeof库函数来计算,结果单位为字节#include
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; }
生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)
有些值是可变的(比如:年龄,体重,薪资)。
不变的值,C语言中用常量的概念来表示,变的值C语言中用变量来表示。
整形常量(整数):int age =18;
浮点型常量(带有小数点的数):float weight=62.5;
字符常量(包含普通字符,特殊字符,数字):char ch=‘z’;
字符串常量:char string[]=" a,b,c";(本质上是定义字符数组来存放多个字符)
(1)整形:short , int ,long int ,long long int,char
(2)浮点型:float,double
#include
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; } 简述printf函数和scanf函数:
printf()函数:输出函数。在双引号内的将进行输出,而%就是控制变量的输出格式,即起到了格式控制的作用,比如%d就是将变量以整型的形式进行打印输出到屏幕上,%c则是以字符型的形式进行打印输出!在逗号后面的就是我们想要输出的变量,在这个地方需要大家进行注意,%格式控制一定要与后面的变量进行意义对应!
scanf()函数:输入函数。跟上面的一样,%也是进行格式控制,不过此处与printf的区别就是此处是进行输入的格式控制,比如%d,就是将我们的输入的内容以整型的形式存储到我们的变量中,此处与前面也一样,都要与逗号后面的变量进行严格的对应,但此处仍然有一个需要大家进行注意的点,比如我们在输入时,我们在%d %d两个%d中间有一个空格进行分隔,那么我们在通过键盘进行输入的时候也要在两个变量中间进行分隔,即我们的输入要与双引号之间的内容进行严格第对应!
作用域(scope)是程序设计中的概念
通常来说,一段程序代码中所用到的名字并不总是有效/可用 的,而限定这个名字的可用性的代码范围就是这个名字的作用域。局部变量的作用域为该局部变量所在的局部范围
全局变量作用域为整个工程,可以是多个源文件(.c文件)中使用。
注:一个.c文件中定义的全局变量在另.c文件中使用时需要使用 extern进行一次声明
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
- 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
- 全局变量的生命周期是:整个程序的生命周期(整个.c文件)。
字符包含
(1)普通字符类型:字母a,b,c…
(2)特殊字符类型:# $ % ^ & * (
(3)数字类型:1 2 3 4
注:字符型数字和常量型数字不完全相同
(4)不可见字符:转义字符\n ,\t, \r
由双引号“”引起来的一串字符(以上4种)
#include
//下面代码,打印结果是什么?为什么?(突出'\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;
}
打印结果:
我们可以看到,我们在输出arr2时出现了乱码形式,为什么会出现这种情况呢?因为在arr2中并不包含字符串的结束标志即’\0’,所以会出现上面的乱码!
注意:
1、在我们用printf()函数以字符串形式进行输出时,只有遇到’\0’时才会停止输出!
2、我们在使用上面arr1这种形式进行定义字符串时,在""里面的字符串中就已经自动包含了字符串的结束标志即’\0’!
3、当我们在使用{}字符串的定义的 方式时我们一定要记得加上字符串的结束标志,虽然我们有时候用不到,但这却是我们必须要做的,这也是一个合格的程序员必备的素养,当然,有的时候确实并不需要加上,在新手期间,
使用库函数 strlen(字符串),注意要引用头文件#include
一道笔试题计算字符串长度
//程序输出什么? #include
int main() { printf("%d\n", strlen("abcdef")); > // \62被解析成一个转义字符 printf("%d\n", strlen("c:\test\628\test.c")); return 0; } strlen()函数,这个函数的作用是求字符串的长度,当遇到字符串的结束标志时将停止,但是需要注意一点,就是字符串的结束标志’\0’本身并不作为字符串长度的一部分(’0不属于字符串的内容)。
上面这一段代码,strlen()括号中的字符串内容为abcdef还有字符串的结束标志’\0’,但是由于字符串的结束标志并不作为字符串长度的一部分,所以字符串的长度为6。
下一段代码,下面有转义字符,了解过转义字符后,此处需要给大家明确一个概念,***转义字符被我们看作成是一个字符,即使它的形式是\后面跟了1个或者多个字符,但strlen()函数只把它看成是一个字符。***所以为什么我们的编译器给出上面的结果也就不难理解了,在上面的结果也就不难理解了,\t是一个转义字符,\62也是一个转义字符,为什么8不跟着一块呢?因为\后面跟的是八进制,即只包含0到7的数字,不能包含8,所以8不被包含在内!后面还有已给\t也是一个转义字符!最终得出14的结果!
假如我们要在屏幕上打印一个目录: c:\code\test.c
我们该如何写代码#include
int main() { printf("c:\code\test.c\n"); return 0; } 实际打印结果:
此处就涉及到了转义字符;
转义字符含义就是转变了原来普通字符的含义:比如上面用到了\t,\n
下表是一些C语言中的转义字符:
基础阶段常用的有:
\n:换行
\t:水平制表符,相当于Tab键
选择是什么?
如果你好好学习,校招时拿一个好offer,走上人生巅峰,你女朋友继续陪在你的身边!
如果你不学习,毕业等于失业,你女朋友跟你分手了!
这就是选择!
#include
int main() { int code = 0; printf("你会去敲代码吗?(选择1 or 0):"); scanf("%d", &coding); if (coding == 1) { printf("坚持,你会有好offer,女朋友陪在你身边\n"); } else { printf("毕业即失业,女朋友跟你分手\n"); } return 0; }
- while语句
- do while 语句
- for语句
while语句样例:
#include
int main()
{
int line = 0;
while (line <= 20000)
{
line++;
printf("我要继续努力敲代码\n");
}
if (line > 20000)
printf("好offer\n");
return 0;
}
执行一定任务后得到一个结果返回值(类比数学中函数概念)
1 调用函数返回值的类型 2 函数名 3(形式参数)
{
函数内容(作用)
}
存放多个(一组)相同数据类型的元素时候使用
数组类型 数组名 [ ]={初始化}
不完全初始化时候自动补0
用下标访问,下标从0开始,最多存放数和方括号内数字相同
#include
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; }
1算数操作符: + - * / %
2关系操作符: > >= < <= == !==
4逻辑操作符: && (且) ||(或)
5条件操作符(三目操作符):表达式1? 表达式2 : 表达式3 ((表达式1成立执行表达式2,否则执行3)
7移位操作符号(了解):>>(右移操作符) <<(左移操作符)
8位操作符:(1)&:按位与 (2) |:按位或 (3)^ :按位异或
9逗号操作符
10下标引用操作符:[ ]
11函数调用操作符:()比如printf/scanf后面的()
(1)由C语言本身提供,不可修改自创
(2)关键字不能作为变量名
auto:局部变量都应该有被修饰,被省略了
enum:枚举
extern:声明外部定义
goto:
register: 寄存器关键字,修饰的变量建议放在寄存器中
signed: 有符号的(分正负)
unsigned:无符号的
static:静态的,C语言种用来修饰变量和函数
(1)修饰局部变量:static修饰局部变量改变了变量的生命周期 让静态局部变量出了局部范围依然存在,到程序结束,生命周期才结束。(本质是改变了变量的存储类型)
(2)修饰全局变量:被static修饰的全局变量只能在所在源文件内部使用,其他源文件不能使用(即使声明)
(3)修饰函数:类似修饰全局变量,被static修饰的函数不再能被另一.c源文件使用(即使声明)//改变了连接属性,由外部连接属性变为内部连接属性
struct:结构体
typedef: 类型重定义(自定义类型名字),写在主函数之前
typedef 顾名思义是类型定义,这里应该理解为类型重命名。typedef unsigned int uint_32; int main() { //观察num1和num2,这两个变量的类型是一样的(把unsigned int重命名了为unit_32) unsigned int num1 = 0; uint_32 num2 = 0; return 0; }
union:联合体(共用体)
void:空
volatile:暂时没用到
注:define和 include是预处理指令,不是关键字
//define定义标识符常量
#define MAX 1000
//define定义宏
#define ADD(x, y) ((x)+(y))
#include
int main()
{
int sum = ADD(2, 3);
printf("sum = %d\n", sum);
sum = 10 * ADD(2, 3);
printf("sum = %d\n", sum);
return 0;
}
- 内存是电脑种重要的存储器,计算机中程序的运行都是在内存中进行的 电脑内存一般是8G/16G,用于临时储存CPU运算数据,
- 因此为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节(byte)。
- 为了能够有效的访问到内存中的每个内存单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
创建的变量是在内存中创建的(在内存中分配空间),每个内存单元都有地址,因此所有被创建后的变量也都有地址那么如何找出(取出)变量的地址呢?
#include
int main() { int num = 10; #//取出num的地址 //注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小地址) printf("%p\n", &num);//打印地址,%p是以地址的形式打印 return 0; } int num = 10; int *p;//p为一个整形指针变量 p = #
32位/64位机器:32根/64根地址线(物理意义上的线)
通电时候–正电为1,负电为0
电信号转化为0和1的二进制序列的数字信号
因此32位机器产生的二进制序列可能性:一共是2^32个(都可以作为地址编号)
用于存放变量的地址(一个编号)
#include
int main() { int num = 10; int* p = #//指针变量p存放变量num的地址 *p = 20;//对指针变量p解引用找到num return 0; }
通过指针变量存放的地址找到某变量
由机器位数决定,与数据类型无关
#include
//指针变量的大小取决于地址的大小 //32位平台下地址是32个bit位(即4个字节):x86 //64位平台下地址是64个bit位(即8个字节): x64 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字节
结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。 比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。 这时候只能使用结构体来描述。
struct Stu { char name[20];//名字 int age; //年龄 char sex[5]; //性别 char id[15]; //学号 };
struct 结构体名
{
数据1
数据2
…}
//打印结构体信息
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);
栈区:局部变量,函数参数(临时的)
堆区:动态的内存分配
静态区:全局变量,static修饰的静态变量
解释复杂代码,方便阅读
注释有两种风格:
C语言风格的注释 /xxxxxx/ 缺陷:不能嵌套注释
C++风格的注释 //xxxxxxxx 可以注释一行也可以注释多行
尊重原创,本文参照链接巨佬的文章及个人搜集整合
http://t.csdn.cn/4qlie