AaronYang风格 C语言挑讲[二][基本类型、运算符和表达式]

AaronYang风格就是:不讲老生长谈的东西,挑主题内难懂的地方细讲,其他总结一笔带过,有口诀教口诀,示例实践出来,文章内容充实。

本文原理理解性方面的较多,但是都被我用gif图片(自己photoshop做的)讲解

更底层的东西,我自己都不懂的,不可能拿出来讲的

本文是针对有学过其他编程语言的来学的,有很多地方我跳过略讲,所以这不是一篇入门的文章

我在看C的时候,其实发现了一些挺好玩的东西,比如宏替换,带符号,不带符号的类型。C的常量定义也不一样。

重点讲位运算符的运算,还有逗号运算符

最主要是每个类型占了多少个字节的理解,以后优化程序可以用到。

要避免不必要的类型转换

 

精彩预览:


比如课外知识,很多人知道怎么去写编程,但原理知道的很少,知道怎么用,比如操作系统32位和64位的关于编程方面的区别

这里讲的很容易理解,自己做了些图片方便理解,如果想直接看,就在本文末最后一节,呵呵

 

 

数据类型基本一览

image

我学C#的,无符号类型和指针没怎么接触过

其他概念:

打开程序时候,数据会存在内存中(个别可能在寄存器中),我们要对每个数据在内存中分配若干个字节,用于存放数据。数据所占用的内存字节数称为该数据的“数据长度”。所以我们要定义不同的数据类型,来安排合适的长度去分配数据存放。于是我们需要数据类型这个概念,不知道有没有听懂了

 

常量

(一) 整型常量

  • 十进制:平常的数字写法,0,22,+11,-3
  • 八进制:0开头的书写形式,例如00,+08,-033,021
  • 十六进制:0x开头的书写形式,例如0x1,-0x121,+0x12,0x21

占用字节:一般微型机中占用2个字节,不分进制,他们的数值范围都是十进制的-32768~+32767

长整型常量:范围 -2147483648~+2147483647,占用4个字节。    

                      书写形式:在整数的末尾加上 l  或者 L           例如: 10L    -011L     +0x15L

么其他的都是短整型常量了。如果整型常量后面没有字母“L”或“l”,而且超过了短整型常量能够表示的数值范围,则自动认为该常量是长整型常量了,例如-32769、 32768、40000都是长整型常量了

 

总结: 整型常量分短整型和长整型两种,又分十进制,八进制,十六进制三种书写形式,使用时,要注意区分。例如,88和88L,数值一样,但是它们在内存中占用不同数量的字节;比如 10,010L,0x10虽然是短整型常量,但是表示的整数值不一样。

 

 

(二) 实型常量

一般形式

               [+ 或者 –]    整数部分      小数点      小数部分

指数形式

               [+ 或者 –]    整数部分      小数点      小数部分  e或者E  [+ 或者 –]  指数(就是普通的整数)

 

       例如 12.345e3      就等于  12.345乘以10的3次方 就是 12345

              12345E-3    就等于 12345乘以10的-3次方 就是12.345

 

总结: 实型常量在一般的微机中占用4个字节,数值范围都是-10的38次方 到 10的38次方,有效数字是7位

            例如: 1.23456789和1.234567是相同的,因为有效数字是7位,所以后两位是无效的

 

(三) 字符常量

就是char类型了,C语言中,字母区分大小写的,‘a’和‘A’ 是不一样的

在内存中,每个字符常量都占用一个字节,具体存放的是该字符对应的ASCII代码值。例如 ‘a’‘A’ ‘1' ‘%’ ‘\r’ ‘\x3d’在内存中的字节中存放的分别是十进制整数 97     65    49    37    13   61

总结:由于整型常量在内存中存放的是整数值,如果其值在0~127之间,C语言规定也可以将其看成一个字符型常量,就是数字当符号使用。例如:整型常量111、70、40可以当做字符常量 ‘o’ ‘F’ ‘(’ 来使用

有个好玩的例子: ‘a’+5 这里a就会被当做97使用,所以等于结果值102,在C#中我也试过了,也是如此

 

(四) 字符串常量

就是字符串,在C#中是string定义的

但是C中定义字符串不是用string的,以后说吧.

例如“aAbBcCdD” 转义字符 \

字符串长度

    普通的不说了,说点特殊的,例如 “ ”是0,       “\\ABCD\\”是6,     “\101\102\x43\x44”是4

虽然每个字符在内存中只占用1个字节,但C语言规定,每个字符串在内存中占用的字节数等于字符串的长度+1,其中最后一个字节存放的字符为“空字符串”,其值为0,书写的时常用转义字符“\0”来表示,在C语言中称为字符串结束标记。例如:字符串“AB”和 “A”的长度分别是2和1,但他们在内存中分别占用3和2个字节,所以 “A”和 ‘A’是不同的,一个占用2个字节,一个占用1个字节

关于这个在C#是否是这样的,我不清楚…

 

(五) 符号常量        #define  符号常量  常量

C编译程序将在程序编译前将所有的符号常量自动替换成对应的常量

变量规范 名字全部用大写字母

例如  #define PI 3.1415926 效果同于C#的      const double PI=3.1415926

        #define A ‘A’      效果等同于C#的      const char A=‘A’

 

宏定义命令的一般格式如下: #define 宏名  一串符号

宏名就等同于变量名,那个一串符号,你可以理解为对应的值

宏替换就是  把名字替换值,然后进行处理。由于宏替换是在编译前进行的,所以宏定义命令属于C语言的”预编译命令”

 

基本例子,理解替换的过程

#define PI 3.14159

#define R 10

#define D (R+R)

#define L PI*D

若程序中用到了L

①先替换成 PI*D

②再将PI替换成3.14156、D替换成(R+R),结果就是3.14159*(R+R)

③这里面还有宏名,再替换R,最后结果就是 3.14159*(10+10)

 

下面是1个特殊的例子:

例子:      #define PI 3.14159

                #define R1 2+3

                #define R2 (2+3)

若求 2*PI*R1的值     宏替换结果是”2*3.14159*2+3”

若求 2*PI*R2的值     宏替换结果是”2*3.14159*(2+3)”

 

 

变量

定义模式跟C#基本一样

类型 变量名=值

类型 变量名

算了,直接举例子

int i;

float i,j;

unsigned short me;

long a1=11L;

unsigned short a1=0111,a2=0x11;

int i=1,j=2,k;

int i,j,k=10;

char c1=‘A’,c2,c3=‘a’;

 

有名常量的定义(就是C#中的const)

在C#中用   const 类型 名称定义的,变量规范都是一样的,名字用全部的大写字母

C中如下:

const 数据类型符 变量名1=初值,变量名2=初值2   等;

跟C# const一样

例如 const char FALE='男',FEMALE='女';

一旦定义,程序运行的时候就不许修改了,否则报错

 

 

运算符(跟C#基本一样,多了几个,这里假设你已经学了其他编程语言)

运算符感觉最基本的

加 减 乘 除 求余数   + – * /   %

正负号 + -

关系运算符    <   >   <=  >=  ==  !=

还有 就是      !       &&    ||

三元运算符(书中写的三元,二元都是三目,二目,我不太习惯)     ?  :

其他符号像 赋值=        逗号  ,         数组中的[ ]     其他基本的 括号 ( )     递增的 ++   --

运算完赋值相关的+=  -= *=    /=  %=

数据长度运算符(sizeof),这个C#中没有

关于成员运算符,我们在C#中,都是 对象 点(.)出来对象中的属性或者方法的,C中用-> 和  .  关于->在PHP中也是用这个的

指针运算符,C#中应该没有吧(& * + – )

比较难理解的有 位运算符(例如<<  >> ^ ~ &  |   &=等),其实C#中也有,我们很少用,过一会讲解一下这个

 

运算相关的还有  就是 结合性,运算的优先级 这个概念

我以前在 Javascript讲过,语言逻辑都是通用的,那里讲的比较详细  点击查看

 

一、基本常见的跳过了

二、长度运算符(sizeof)

打开C-Free5

image

sizeof 是C里面的关键字 并非函数,意思是c 所占的内存多少 单位是字节
getch(); 用此命令可以在运行的的时候,按任意键退出 ,如果没有此命令,屏幕闪一下就没了(程序结束就退出) 所以看不见结果

等同于C#中的Console.ReadLine();

 

image

 

 

重点讲解一下 位运算符

编程中: 0代表false,假,1代表true,真,有句口诀,非0即真

 

一、位逻辑运算符

                     使用数目和位置                              对象类型                              结果类型                     结合性

位非 ~              单目前缀                                       整型                                      整型                         自右向左

位与 &             双目中缀                                       整型                                      整型                         自左向右

位或 |               双目中缀                                       整型                                      整型                         自左向右

按位加 ^         双目中缀                                        整型                                      整型                         自左向右

 

image

关于16进制转2进制的对照表格

image

【例一】

设变量定义如下: unsigned short a=0111,b=0x53

先把  a 无符号八进制转换成二进制:     0000 0000 0100  1001

         b 无符号十六进制转换成二进制:  0000 0000 0101 0011

①~a  把二进制是0的位置变成1,是1的变成0(对应的二进制就是1111 1111 1011 0110),然后转换成八进制为0177666,运算后a不变

②a&b,两两位对应,有0则0,对应的二进制是(0000 0000 0100 0001),然后转换成八进制为0101,运算后a不变

③a|b,两两位对应,有1则1,对应的二进制是(0000 0000 0101 1011),然后转换成八进制为0133,运算后a不变

④a^b,两两位对应,相异则1,对应的二进制是(0000 0000 0001 1010),然后转换成八进制为032,运算后a不变

 

 




二、位移位运算符

                   使用数目和位置                运算规则              对象类型                              结果类型                     结合性

左移 <<             双目中缀           a<<b.a向左移b位          整型                                      整型                        自左向右

右移 >>             双目中缀           a>>b.a向右移b位          整型                                      整型                        自左向右

移位时,移出的位数全部丢弃,移出的空位补入的数与 左移还是右移有关

如果是左移,则规定补入的数全部是0,;如果是右移,如果不带符号,则补入的数全部是0;如果带符号,则补入的数全部等于原数的最左边位上的数(即原数的符号位)

 

下面假设a已经是转换成二进制的,原本本来a=47,现在转换成了二进制101111

无符号左移,带符号左移,他们两个一样的,我做张图片演示

 

无符号右移

位移符号演示右移无符号

带符号右移
带符号右移(最左边是0,就补0,最左边是1,就补1)

移动完后,在将二进制转换成十进制,这就是位移位运算符

 

 




三、位自反赋值运算符

      功能类似常用的 +=  -=,运算完了,改变原有的值

主要是这5个: &=      |=      ^=      <<=         >>=

这里不讲了,就是经过位移运算后,改变原有的值,第一部分,第二部分讲的都是运算后不改变原有的值

 

 

 

 

 

 

表达式(跟C#90%一样)

  1. 算数表达式
  2. 关系表达式
  3. 逻辑表达式
  4. 赋值表达式
  5. 逗号表达式
  6. 条件表达式

重点讲一下,C#中没有的 逗号的特殊用法,可以组成逗号表达式

逗号除了声明变量时 int a,b=10,还有函数参数也是用逗号来间隔的

但是那里的逗号都不是运算符,在C中,逗号可以是一种运算符。下面我们通过几个例子学习一下

逗号运算符,用它可以将两个表达式连接起来。如:

3+5,6+8

称为逗号表达式,又称为“顺序求值运算符”。逗号表达式的一般形式为

表达式1,表达式,表达式3……表达式n

最终的结果都是以最后一个表达式的值为准,也就是表达式n的值

例如上面一个逗号表达式的值就是6+8,也就是14

 

例一

image

这里先算3乘以5等于15,然后把值赋给了a,a等于15了,然后15乘以4,最终整个表达式的值就是60了

例二

image

C语言表达能力强,其中一个重要方面就在于它的表达式类型丰富,运算符功能强,因而c使用灵活,适应性强

 

 

类型转换的小例子,提醒优化(变量=表达式)

C#中有强制转换和隐式转换,C也有,自动转换规则和强制转换规则,99%和C#一样

  1. 表达式计算中数据类型的自动转换规则 :参加运算的各个数据都转换成数据长度最长的数据类型,然后计算-----”就长不就短“。

    例如:image

  2. 运算结果存入变量时数据类型的自动转换规则 :先将运算结果的数据类型自动转换成左边变量的数据类型,然后再赋予该变量-----”就左不就右“。

    例如:image

  3. 运算结果的强制性数据类型转换规则 :跟C#一样,例如 (int)14.5 即 14

    例如:image

  4. 避免转换的小例子

    例如:image

 

课外知识

一个字节等于8个二进制位;即 1byte=8bit

计算机采用二进制的,8=2^3,通常最高位为符号位

  二进制数系统中,每个0或1就是一个位(bit),位是数据存储的最小单位。其中8bit就称为一个字节(Byte)。计算机中的CPU位数指的是CPU一次能处理的最大位数。例如32位计算机的CPU一次最多能处理32位数据。
  Bit,乃BInary digit(二进制数)位的缩写,是数学家John Wilder Tukey提议的术语(可能是1946年提出,但有资料称1943年就提出了)。这个术语第一次被正式使用,是在香农著名的《信息论》,即《通信的数学理论》(A Mathematical Theory of Communication)论文之第1页中

所以说64位操作系统,每次读取的位数更多,所以处理数据更快了,但可能存在兼容性的问题

下面讲一个小题目了

image

回忆本篇第一部分

image

short类型的字节长度2

long类型长度是4

下面用图片解释一下

变量b3是4字节的,存放65536后,对应的二进制位数如下:

image

将b3的值赋予变量a的时候,b3的4字节中低16位数据(右边2字节)组成的新值就赋予变量a了,最后转换成十进制显示,就是0

 
 
 

学习总结

  1. 对常量,宏替换,变量 原理性的理解和使用
  2. 数据长度,进制转换的理解
  3. 位运算符的理解和使用
  4. 逗号运算符的使用
  5. 占用字节数的理解和实践
posted @ 2013-06-16 01:31  AYUI框架  阅读(984)  评论(6编辑  收藏  举报