“这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战”
学习c语言的境界
境界一:c语言的基本的语法
境界二:通过c语言语法锻炼自己的逻辑思维和编程能力
境界三:通过指针操作内存
一.理解内存
1.1内存划分
linux系统的内存的划分见上图,由于32位系统最大能访问的内存2^32(4G),但是用户外接的物理内存大小不确定,所以内核就引入了虚拟内存的概念,mmu(内存映射单元)将物理内存映射成虚拟内存。0-3G属于用户空间,每一个程序的运行都有自己的0-3G的空间,用户空间有多份,但是内存空间只有3-4G一份
刚开始在.ro段这老犯一些错误,
eg:
char *p = "hello";
char *q = "world";
在执行strcat(p,q);时就会在Ubuntu内编译时会见到段错误,刚开始不理解,问了老师才明白,因为p指针指向只读段,这样写入会发生段错误。可以把被拼接的的字符串定义成字符数组就解决了。
eg:
char arr[] = "hello";
1.2c语言中的内存的分配
1.2.1变量类型:(32位)
基本类型
| 1.字符类型 | 字节数 | 符号位 | 数据位 | 数据范围 | |
|---|---|---|---|---|---|
| char | 1字节 | 7 | 6---0 | [-128,127] | |
| unsigned char | 1字节 | 7---0 | [0,255]-->[0,0xff] |
| 2.整型 | 字节数 | 数据范围 |
|---|---|---|
| short | 2字节 | [-32768,32767] |
| unsigned short | 2字节 | [0,0xffff] |
| int | 4字节 | [-2147483648,2147483647] |
| unsigned int | 4字节 | [0,0xffffffff] |
| long(long int) | 4字节 | |
| long long(long long int) | 8字节 |
| 3.实型 | 字节数 | |
|---|---|---|
| float | 单精度浮点类型 | 4字节 |
| unsigned short | 双精度的浮点类型 | 8字节 |
4.枚举类型:enum 4字节
- 枚举:属于基本类型,在32位操作系统上,枚举占用的大小是4字节,它是有限数据的罗列。
- 定义格式:
enum aa{
ONE ,
TWO,
THRE=10,
FOR,
};
- 1.枚举类型的成员和成员间是逗号
- 2.枚举类型中的成员默认第一个是0,后面的成员依次加1
- 3.枚举类型中的成员被赋值之后,后面的成员依次加1
- 4.枚举类型占用的大小就是4字节
- 5.有限数据的罗列
enum {
ADDSTU=1,
VEWSTU,
SOTSTU,
MODSTU,
DELSTU,
QUTSTU,
};
5.构造类型:
- 数组类型 char [2] ; int [3];
- 结构体 struct
- 共用体 union
6.指针类型
char * ; int *;
long *; void *;
所有的指针都占4字节
7.空类型
void
1.2.2变量的定义
- 数字,字母,下划线组成,不能以数字作为开头 int _a12;
- 不能和关键字重复(例如:int char struct... 32个)
- 变量区分大小写
- 见名知义
二.进制转化
| 进制 | 前缀 | 例如 |
|---|---|---|
| 二进制 | 前缀0b | 0b 100 0010 = 2^6+2^1=66 |
| 十进制 | 66 | |
| 八进制 | 前缀0 | 0102 |
| 十六进制 | 前缀0x | 0x42 |
1K 0x0400 [2^10]
1M 0x0010 0000 [2^20]
1G 0x4000 0000 [2^30]
2G 0x8000 0000
3G 0xc000 0000
4G 0x0001 0000 0000
5G 0x0001 4000 0000
三.数据存储问题
所有的数据是以补码的格式来存储的,正数的源码,反码,补码都是它本身负数的补码按照如下格式转化
eg:char a = -5;
源码 1000 0101
反码 1111 1010 :除符号位不变,其他位取反
补码 1111 1011 :在反码的基础上加1
补码转化源码和源码转补码的过程是一样。
补码的补码是源码
四.常量的表示
1.字符常量
char a;
man ascii
'A' --->65
'a' --->97
'z' --->122
'n' --->110
'\n'--->\转义,换行 10
'\a' --->bell
'\t' --->Tab
'0' --->48
'\0'--->0
'\101'--->A //对应一个字符
'\x41'--->A
'\0x411'越界,逃出16进制。//一个转义就一个字节,
'\1011'--->A1
转义字符可以转义八进制或者16进制的数,没有十进制转义为字符(ascii表中)
'\101'--->转义为字符'A' 八进制的转义
'\x41'--->转义为字符'A' 十六进制的转义
printf("%c\n",'\101');
printf("%c\n",'\41');
2.整型常量
0b11101
87
0775
0xabc113c
3.实型常量
3.14
3.1e2 //3.1*10^2,e or E
3.1e-2
4.标识常量
define
5.字符串常量(c语言中没有字符串类型,可以存在字符数组)
"helloworld"
五.输出的用法
printf("控制格式",输出的数据)
printf("%c",a); //以%c的型式显示a的值
printf("%u",a); //%u无符号的正数
printf("%d",a); //整数
printf("%04d",a); //打印的数据占四个格,如果不足补充0
//04 是指,输入五位时原样输出
printf("-4d",a); //左对齐
printf("%#o",a); //八进制
printf("%#x",a); //十六进制
printf("%ld",a); //显示的是long int
printf("%lld",a); //显示的是long long int
printf("%#llx",a); //十六进制显示的是long long int
printf("%s",a); //显示字符串
printf("%p",a); //显示地址,变量在内存上的内存单元的编号
printf("%f",a); //显示浮点数,小数点后6位
printf("%.2f",a); //显示浮点数后两位,四舍五入
printf("%lf",a); //显示double
printf("%e",a); //指数的形式显示浮点数
printf("%g",a); //显示小数点后的有效位
六.标准输入
scanf("控制格式",&变量);从终端上读取结果到变量中
scanf("%c",&a); ==>输入字符到a变量
scanf("%d",&a); ==>输入整数到a变量
scanf("%f",&a); ==>输入小数到a变量
scanf("%s",a); ==>输入字符串到a数组中,在输入的时候字符串间
==>不能有空格,但是gets是可以的。
scanf("%[^\n]",arrary); ==>表示除了'\n'之外的字符都输入到
==>array数组中,他就可以和gets等价
ret = scanf("%d%*c%c",&a,&b); ===>%*c吃掉任意的一个字符,两个**两个字符
ret = scanf("%d,%d",&a,&b); ===>第一个返回错了就都是0,scanf是返回第一个错误为止的正确的个数
注:scanf的返回值是表示输入成功的项目的个数 可以通过判断返回值来判断,输入的数据是否正确。
返回值的判断实例:
#include <stdio.h>
int main(int argc, char const *argv[])
{
char w;
int n;
int m;
int ret;
retry:
ret = scanf("%c,%d,%d",&w,&n,&m);
printf("input()");
if(ret != 3)//输入成功的个数如果不为3
{
while(getchar()!='\n'); //把所有的字符都吃掉
goto retry;
}
printf("ret = %d\n, w = %d,n = %d,m = %d\n",ret,w,n,m);
return 0;
}
七.输入或输出字符
int getchar(void); //scanf("%c",&ch); ===> ch=getchar();
功能:从终端上获取一个字符
参数: @无
返回值:读取到的字符对应的数值
int putchar(int c); //putchar(ch) ====>printf("%c",ch);
功能:从程序向终端上输出一个字符
参数: @c :想要输出的字符
返回值:成功返回输出的字符,失败返回EOF(-1)
例子如下:
/*
ch = getchar();
putchar(ch);
*/
putchar(getchar());
putchar(10); ===>'\n'
putchar('\n'); ===>'\n'
putchar('\012');===>'\n'
putchar('\n');
putchar(0101);
putchar('\101');
putchar('\n');
八.输入或输出数组
char array[100];
char [] gets(char s[]);
gets(array);===>scanf("%[^\n]",array)
功能:从终端上读取一个字符数组
参数:
@s:数组的首地址
返回值:数组的首地址
📢注意:gets输入多少就会输出多少,不考虑数组的大小超过执行的时候就会出错。gets可以读取空格。gets会把'\n'替换成'\0' ,'\0'表示字符串结尾 hello world\0
int puts(char s[]); //puts(array) ===>printf("%s",array)
功能:输出一个数组
参数:
@s:被输出的数组
返回值:成功返回输出的字符的个数,失败返回EOF(-1)
注:puts会输出换行
九.c语言中的注释
// 单行注释
/*
*多行注释
* */
#if 0
多行注释
#else
没有注释的部分
#endif