// 注意:
// 用/*.......*/
// 内部的内容是注释内容
// 在C语言中 //之后是注释的内容
// 在脚本文件或者配置中,注释的方法和C语言的方法不一样
//================================
//一.编辑器
// vim
//二.编译器
// gcc(依赖于cc)
//三.打印hello world
/*
一.笔试题
1.从一个.c文件,编译成可执行文件需要经过哪些阶段?
需要经历4个阶段
预处理->编译->汇编->链接
2.在C语言中以#开头的内容代表的是预处理
3.预处理阶段需要做的操作
1)文件包含 #include
2)条件编译 #ifdef #ifndef #if #else #elif #endif ...
3)宏定义 #define
4.在包含头文件时,头文件左右使用尖括号<>和使用双引号"",有什么区别
#include <stdio.h>
会从指定目录(/usr/include/)中查找头文件,如果找不到会报错
#include "func.h"
会先从当前目录(就是.c文件所在的目录)中查找头文件,
如果找不到,再从指定目录(/usr/include/)中查找头文件,
如果再找不到,就会报错
5.注意 : 在C语言中是有字符串的,但是没有字符串类型
===========================================================
二.介绍头文件
stdio.h->是标准输入输出的头文件
三.每一个程序必须要有一个main函数
main函数也叫做主函数
当程序员在执行./a.out时,会先从main函数进入,
按照从上往下的顺序逐行逐行的执行代码
最后会从main函数退出
四.写C语言程序的阶段
第一阶段 只写一个.c文件,.c文件中只写main函数,
把所有功能都堆到main函数中
第二阶段 只写一个.c文件,.c文件中除了有main函数以外
还有其他的功能函数,在main函数中可以调用功能函数
第三阶段 在一个项目工程中存在多个文件
main.c 存放main函数和功能函数的调用
func.c 存放功能函数的实现
func.h 存放功能函数的声明包括各种定义
makefile 存放编译规则
第四阶段 把func.c文件制作成库文件
制作静态库
制作动态库
五.main函数
1) 函数的声明
函数的返回值类型 函数名 (参数列表) ;
int atoi (const char *nptr) ;
int rand (void) ;
2) 函数的实现
函数的返回值类型 函数名 (参数列表)
{
函数的功能代码
}
3) 函数的调用
函数名 (参数) ;
printf ("Hello World!") ;
*/
#include <stdio.h>
int main(void)
{
printf("Hello World!");
/*
printf是一个函数,功能是用来打印输出的
具体一些:可以把双引号"..."中的内容打印输出到标准输出(终端)
在C语言中,双引号引起来的内容叫做字符串
"Hello World!"->这是一个字符串
在C语言中,单引号引起来的内容叫做字符
'A' 'a' '1' '0'->这些都是字符
其实字符串是由一个一个单一的字符组成的,
最后有一个默认的结束标志,叫做'\0'(尾0)
"9527" => '9' + '5' + '2' + '7' + '\0'组成
==========================================
练习题
"0" 和 '0' 和 0 和 '\0'的区别
"0" 这是一个字符串,是由'0' + '\0'组成
'0' 这是一个字符,ASCII值是48(十进制)
0 这是一个整数,数字0
'\0' 这是一个转义字符,是尾0
*/
}
=======================================================
/*
面试题
1.记住特殊字符的ASCII码
'\0' 0
'\n' 10
'0' 48
'A' 65
'a' 97
printf的使用方法
ascii的由来:就是日常生活中用到的符号和计算机世界中数字的对应关系
其实字符代表的含义就是一个整数(ASCII值)
在Linux环境下可以使用man手册来查阅ascii表
在正常环境下ASCII表,表示[0 ~ 127]一共是128个字符
但是在有些环境下,表示[0 ~ 255]一共是256个字符
1.转义字符(转义字符也是字符,是由一个 \ + 某些内容组成的字符)
是可以从ascii表中查到的
转义字符 ASCII值 含义
'\0' 0 尾0,字符串的结束标志
'\n' 10 换行符,会把光标换到下一行行首的位置
'\r' 13 回车符,会把光标回到当前行行首的位置
'\t' 9 水平制表符
'\v' 11 垂直制表符
注意 :
1)'\0'是在做字符串操作时会大量使用
2)'\n' 和 '\r'在无线模块的模组中是进行使用(WiFi GPRS NB-IoT)
*/
2.标准化输出格式(并不是字符,是由'%' + 某个内容组成的)
前面的%,叫做占位符
是在使用printf输出时的一些特殊的格式
%d 十进制整数输出
%o 八进制整数输出
%x%X 十六进制整数输出(%x<a b c d e f> %X<A B C D E F>)
%u 无符号整数输出(没有正负号)
%c 字符输出
%s 字符串输出
%f 浮点数输出(默认输出小数点后6位)
%% %本身
%p 地址输出(也可以表示为数据在内存中的存储形式)
*/
一般来说%p是用来打印地址的,但是在底层内核驱动开发中,
也可以使用%p打印变量在内存中是如何存储的
i = 0x64
int i = 100; //00000000 00000000 00000000 01100100
// i = 0x00000064 => 0x64
#include <stdio.h>
int main(void)
{
//printf("Hello World!"); 打印出 -> Hello World!zack@01day$
//printf("Hell\0o World!"); 打印出 -> Hell
//printf("Hello World!\n"); 打印出 -> Hello World!
// zack@01day$
//printf("dsadasdaHello World!\r");
// 打印出 -> zack@01day$ o World!
//printf("123\t456\t789\t");打印出 -> 123 456 789 zack@01day$
printf("123\v456\v789\v");
/*
123
456
789
zack@01day$
*/
return 0;
}
/*================================================================
标准化输出格式
是由 % + 某个内容组成
输出格式 对应类型 含义
d / i int 十进制整数输出(%i是老式写法)
o unsigned int 八进制整数输出(不会输出前置0)
u unsigned int 无符号十进制整数输出
x / X unsigned int 无符号十六进制整数输出
f / lf float(double) %f是float %lf是double(尤其是scanf函数)
e / E double
g / G double
c char 字符型
s / S char * 字符串
p 地址
% 百分号本身
================================================================*/
/*================================================================
变量
一.变量的含义
变量就是用来存储数据的
(数据会存放在内存中,在内存中是以二进制补码的形式来存储数据的)
二.变量的定义
数据类型 变量名 ;
int a ;
float f ;
1)基本数据类型和复合型数据类型
基本数据类型
整型 有符号/无符号 short int long
实型 有符号 float double
字符型 有符号/无符号 char
如果定义变量时,没有指定有符号(signed)/无符号(unsigned),
默认按有符号数据类型处理
signed int a;//有符号的整型变量a
unsigned int a;//无符号的整型变量a
int a;//有符号的整型变量a
2)通过sizeof可以查询
sizeof是一个运算符,不是一个函数
sizeof(数据类型/变量名)
运算的结果是所求内容的字节大小,是以字节为单位
1个字节(byte) = 8个位(bit) //在不同硬件环境下,基本都相同
1个字(word) = 2 / 4个字节(byte) //在不用硬件环境下,结果不同
3)通过官方头文件的定义进行查看
/usr/include/limits.h
4)在不同硬件或不同系统环境中测试结果是会不同的
如果在64bit环境下测试的最长数据类型是8个字节(64bit)
如果在32bit环境下测试的最长数据类型是4个字节(32bit)
5)变量的命名要求
1> 变量名是由数字 字母 下划线组成,但是不能以数字开头
int a; int a1; int a_1; int _a1; //Bingo
int 1a; int 1_a;//ERROR
2> 变量名是区分大小写的
int a;
char A;
3> 变量名不能与C语言的关键字重复
关键字 : void char short int long float double signed unsigned
4> 定义变量时,变量名要见名生义
int score;
int temp_value;
三.变量在定义时需要遵循的点
1) 变量应当是先定义再使用(一般来说变量的定义放在函数开头的位置)
2) 便于编译时检查错误,不同类型的变量有不同的运算要求
3) 定义变量之后,数据类型确定了,将来在内存中所占用的存储空间也就确定了
四.变量的初始化
数据类型 变量名 = 数值 ;
int a = 100 ;
char c = 'A' ;
float f = 3.14 ;
注意 : 要养成一个良好的编程习惯,变量定义之后一定要有初始化
五.变量的存储
注意 :
1.无论是<数组的下标>还是<二进制的位>还是<芯片的管脚>都是从 0 开始数
2.在做内核驱动时,一般来说常用无符号类型,为了防止符号的干扰
变量是存储在内存当中定,并且是以二进制补码的形式存储的
为了举例子方便,就使用char类型来举例子
'A' 'Z' 'a' 'z' '0' '9' '+' ....字符
char c = 'a'; //c = 97;
char c = 97;
char c = 13; //c变量是char类型的,应该要存储字符,为什么能存储整数?
有符号的char类型占用1个字节(8bit)的存储空间[第7位 - 第0位]
第7位 表示的是符号位(0正 1负)
第6位 - 第0位 表示的是数据位
[127 - -128]
[01111111 - 10000000]
char c = -13;
c = 0xF3; //11110011
==================================================
原码和补码
原码就是给程序员看的,把操作数从别的进制转换成二进制就是原码
补码就是给机器看的,如果操作数为正,原码等于补码,
如果操作数是负的,原码不等于补码,无论是原码转补码,还是补码转原码
除了符号位不变,其他位按位取反再加1
char c = -13;
原码 1 0 0 0 1 1 0 1
补码 1 1 1 1 0 0 1 1
0xF3
为什么在内存中使用补码存储数据,而不是原码
1.为了保持0的唯一性
char c = 0;
0 0 0 0 0 0 0 0 +0
1 0 0 0 0 0 0 0 -0
加法的运算速度要比减法运算速度快
3 - 2 -> 3 + (-2)
00000011 + 10000010
==================================================
无符号的char类型占用1个字节(8bit)的存储空间[第7位 - 第0位]
第7位 - 第0位 表示的是数据位
[255 - 0]
[11111111 - 00000000]
================================================================
float存储类型,4字节32位
第31位 表示的是符号位
第30位-第23位 表示的是整数部分
第22位-第0位 表示的是小数部分
例子:
3.2
操作数是正的所以最高位是 0
整数部分是3 0000011
小数部分是0.2 小数部分一直乘以2取整数
0.2 * 2 = 0.4 0
0.4 * 2 = 0.8 0
0.8 * 2 = 1.6 1
0.6 * 2 = 1.2 1
0.2 * 2 = 0.4 0
...
================================================================*/
#include <stdio.h>
int main(void)
{
char c = -13;
printf("c = %d\n", c);
printf("&c = %p\n", &c);
printf("c = %p\n", c);
return 0;
}
================================================================*/
#include <stdio.h>
int main(void)
{
printf("sizeof(char) = %ld\n", sizeof(char));
printf("sizeof(short) = %ld\n", sizeof(short));
printf("sizeof(int) = %ld\n", sizeof(int));
printf("sizeof(long) = %ld\n", sizeof(long));
printf("sizeof(float) = %ld\n", sizeof(float));
printf("sizeof(double) = %ld\n", sizeof(double));
return 0;
}
=============================================================#include <stdio.h>
int main(void)
{
//int a = 100;
float a = 3.14;
printf("a = %f\n", a);
return 0;
}
/*================================================================
scanf函数
段错误 (核心已转储)
scanf函数是用来录入数据
注意 :
1.在scanf函数的双引号中只写标准化输出格式即可
2.在scanf函数的双引号中千万不要写换行符('\n'<和缓冲区有关>)
3.在scanf函数的双引号之后,需要使用地址,而不是变量名
编译器是不检查段错误,只有在程序运行时会提示出段错误
段错误 (核心已转储) : 主要是因为操作内存不当引起的
================================================================*/
#include <stdio.h>
int main(void)
{
int a = 100;//定义了整型变量a,并且初始化为100
printf("a = %d\n", a);//通过printf函数打印a变量的值
printf("请输入a变量的值 : ");
scanf("%d", a);//通过scanf函数为a变量录入数值
printf("a = %d\n", a);//通过printf函数打印a变量的值
return 0;
}