跟我一起学C语言(第二天)

来源:互联网 发布:詹姆斯季后赛数据排名 编辑:程序博客网 时间:2024/04/30 17:29
第二天
推荐学者学习期间阅读以下书籍:
基础不好的:谭浩强的c语言(适合初学者)
基础一般的:c和指针 
基础不错的:c语言的深度解剖


计算机体系架构:运算器、控制器、存储器、输入设备、输出设备
运算器和控制器组成了CPU(处理器)
存储器:外存(硬盘)、内存、寄存器


硬盘(存放程序) ——> 内存(程序加载到内存)——> 寄存器 ——> 处理器(程序是否运行主要由处理器决定)


冯诺依曼结构:只需要一个内存(这个内存中既可以存放数据,又可以存放指令),指令给处理器识别。
内存中要有空间存放数据和指令,但是又不能混乱,为了避免混乱冯诺依曼结构内存
出现了一个概念(代码分段),数据被存放到一个指定空间中,指令存放到另一个空间中。
 
常见的代码分段:假设现在有一个内存
 (非常重要)elf格式头——代码段(存放指令)——数据段(已初始化的静态变量)——BSS段(未初始化的静态数据或者被初始化为0的数据)——只读数据段(常量)——栈——堆
 
哈弗结构:至少要有两个内存(一个存放数据、一个存放指令)


写程序,可以使用某种语言。可能使用机器语言,可能使用汇编语言,还可能使用高级语言。
所谓的高级代表的是给人看的,高级语言执行效率低,机器语言执行效率最高。开发效率和执行效率成反比。

机器语言:机器识别二进制补码。

高级语言到机器语言的过程其实就是一个翻译的过程。
谁能翻译?编译器或解释器

库:函数源码的二进制形式。
头文件:存放的是函数声明。


ubuntu中头文件主要存放在 /usr/include 
ubuntu中库文件主要存放在 /lib/usr/lib 


十进制数据转化为二进制

假设一个32进制:63   3 * 32^0 + 6*32^1

公式:比如有一个x进制的数据ab,转化为十进制
b * x^0 + a * x^1


110010010001转化为八进制:110 010 010 001 ==> 6221 <==> 06221八进制前缀是0(零)
110010010001转化为十六进制:1100 1001 0001 ==> c91 <==> 0xc91 十六进制前缀是0x

要求熟练:十进制转二进制   二进制转为八进制、十六进制

进入ASCII表的命令:man ascii
在表中,所有的字符对应的值>=0。ASCII值<=32为不可见字符。
'  '为32   '\n'值为10  '0'值为48   'A'值为65  'a'值为97    相同的大写字母比小写字母小32

c语言的特殊符号:
1、关键字   c中一共有32个关键字
2、标识符  
a、以数字、字母或者下划线组成
b、不能以数字开头
c、不能与关键字重名
标识符用于变量名,数组名,函数名,指针名,结构体变量名。
注意:尽量不要使用下划线开头,因为在系统环境中有很多的变量或者宏以下划线开头的。


注释方法:
1、//

2、/*   */

3、
#if 0

#else 


#endif

数据类型(描述的作用) 
1、基本类型:char short int long float double   long long 
2、构造类型:数组、结构体、共用体
3、指针类型:一级指针、二级指针、数组指针、函数指针、结构体指针
4、空类型:void

NULL 是个地址,地址的值是0

查看NULL的定义命令:vim -t NULL

变量、常量
 (非常重要)赋值语句:左端和右端类型要保持一致,左端必须是变量,右端可以是变量也可以是常量。

字符串常量:默认存放在只读数据段;字符串常量一定以'\0'结尾
0 '0' '\0' "0"<==>'0''\0'组合

gcc -c xxx.c -o xxx.o
objdump -s 2.o 查看代码分段信息

如何定义变量?
存储类型  数据类型  变量名;(这个定义非常重要,相当于是一个数学公式一样)

动态变量可以初始化多次,静态变量只能初始化一次。

变量被分成全局变量和局部变量,全局变量是静态的,局部变量可能是静态的可能是动态的。
如果变量存放到数据段、BSS段,这种变量是静态的。
如果变量被存放到栈或堆中,一般是动态的。

auto:只用于局部变量,一定是动态的。如果没有初始化默认值是随机的。
register:只能用于局部变量,也是动态的。当某个变量大量频繁的被调用时可以使用register
 
extern:可以引用其他文件中的全局变量/函数定义/全局数组
static:
作用1:只能初始化一次
作用2:如果全局变量的前面加了static,那么这个全局变量不能被其他文件引用了。
静态变量如果没有初始化,默认值为0.

按照存储区域区分:
1、全局变量:一定是静态的
2、局部变量:如果使用了auto或者register就是动态的,如果使用了static就是静态变量。

按照状态区分:
1、动态变量:一定是局部变量(存储类型可能是auto或者register)
2、静态变量:
全局变量:可能没有存储类型(绝对不可能出现auto或者register),可能出现的是static或者extern
局部变量:一定使用了static

四种存储类型相互之间是互斥的。


原码、反码、补码问题:
无符号数据:unsigned int a = 10;
原码:28个0 + 1010
反码和补码和原码完全一样


有符号数据: 
有符号正数:int a = 10;
原码:最高位是符号位,其中0代表正数,1代表负数。
0 27个0 1010
反码、补码和原码完全一样。

有符号负数:int a = -10;
原码:1 27个0 1010
反码:1 27个1 0101   在原码基础上符号位不变,其他位取反。
补码:1 27个1 0110   在反码基础上+1


数据类型强制转换: 变量1 = 变量2 当变量1和变量2数据类型一致时直接赋值不需要强转。
 当变量1和变量2数据类型不一致时,右端照着左端的数据类型抄到右端,最后在变量2的前面加()


例子: xxx a;
        yyy b;
 a = (xxx)b;
例子:
int *(*q)(int *,int (*)()); 
int *p;
q = (int *(*)(int *,int (*)()))p;




运算符
算数运算符:+ - * / % ++ --
除法符号:如果分子分母都是整数,结果取整。
求余符号:分子和分母必须是整数。
自增符号:前缀和后缀     
后缀优先级高于前缀优先级,但是后缀虽然优先级高但是要先取原有值,当整个表达式运行完成后再自增。


关系运算符: > >= < <= == !=   
这种运算符是双目运算符,构成的整个表达式的值是逻辑值(真、假)
(50,67]  50 < a <= 67错误的。
a > 50 && a <= 67


例子:去写一段程序判断变量a和10是否相等。
if(a == 10)正确的
if(a = 10)逻辑是错误的

逻辑运算符:&& || !
逻辑与:表达式1 && 表达式2
表达式1   表达式2     结果
  真         真        真
  真         假        假 
  假      不需要判断   假


逻辑或:表达式1 || 表达式2
表达式1   表达式2     结果
  真      不需要判断   真      实际表达式2是没有执行的
  假      真           真 
  假      假           假


基本的优先级问题:  后缀自增自减 大于 前缀自增自减 大于  逻辑非 大于 * / % 大于 + - 大于 所有关系运算符 大于 逻辑与和逻辑或


条件运算符:c语言中唯一的一个三目运算符
 表达式1 ? 表达式2 : 表达式3 
 如果表达式1为真,则整个语句结果是表达式2;如果表达式1为假,整个语句结果是表达式3























原创粉丝点击