C中 类型 运算符与表达式

变量

限制:1.字母+数字   (第一个字符必须为字母) 

2."_"视为字母  一般情况是 _使用在命名较长的变量命中以提高名字的可读性  例如:first_const 起到驼峰命名的作用    例程中的变量名一般使用 _ 开头命名 所以我们在命名时不要使用_ 开头

3.区分大小写   变量名一般小写  符号常量名全部大写

4. 内部名:只在自身.c文件中使用的 命名标识符 长度最长为31个字符 (这一部分存疑,没有试出来)

外部名:用于不同.c 文件调用的函数名,变量名 有效识别长度为6位 且不区分大小写 , 需要保证6位字符的唯一性   baf  baF 在调用时将被视为同一外部链接   

5.原则 : 命名要尽量重表面即可看出 变量或函数的用途  局部变量也尽可能简洁短小

数据类型及长度

char        字符型     占一个字节

int           整型        通常反应机器中整数的最自然长度

float        单精度浮点类型

double    双精度浮点类型

在i基本前加限定符(这是int 可以省略)   

short  int sh;---->short sh;  short <=int 长度  至少为16位

long  int sh;---->long sh;  long 类型至少为32位 

long double ; 

类型限定符 signed  与  unsigned 用于限定 char 类型或任何整型 (char   short  int long) 不包括浮点型

这里介绍两个计算基本类型所占空间的 头文件

sizeof()  返回 基本数据类型的 长度(字节B)

1B(Byte 字节)=8bit,

1KB (Kilobyte 千字节)=1024B, 

1MB (Megabyte 兆字节 简称“兆”)=1024KB, 

1GB (Gigabyte 吉字节 又称“千兆”)=1024MB, 

1TB (Trillionbyte 万亿字节 太字节)=1024GB,其中1024=2^10 ( 2 的10次方), 

1PB(Petabyte 千万亿字节 拍字节)=1024TB, 

1EB(Exabyte 百亿亿字节 艾字节)=1024PB, 

1ZB (Zettabyte 十万亿亿字节 泽字节)= 1024 EB, 

1YB (Yottabyte 一亿亿亿字节 尧字节)= 1024 ZB, 

1BB (Brontobyte 一千亿亿亿字节)= 1024 YB.

常量

预编译处理器形式定义  #define

常量定义 :  #define  名称  + 值(又称为 宏定义)    

#define  LENGTH  10;

#define  WIDTH  5;

#define  NEWLINE  '\0';

const  关键字 定义

const  +  类型  +  命名  = 值

const  int  LENGTH = 10;

const  int  WIDTH = 5;

const  char NEWLINE = '\0';

两种方式有什么异同:

1. 编译器处理方式

     define 常量是在预编译是进行 赋值的的

     const 是在编译时进行赋值的

2. 类型检查

     define 不声明常量类型  编译器不进行类型检测 比较危险     

     const 需要进行类型声明  并对常量值是否匹配类型进行检测

3. 内存空间

     define - 不分配内存  给出的是立即值 有多少次使用就进行多少次替换,在内存中有多个拷贝,消耗内存较大

      const - 在静态存储区中分配空间  在程序运行过程中内存中只有一个拷贝

4. 其他

在编译时  编译器通常不为 const 常量分配存储空间,而是将他们保存在符号表中,使得他成为一个编译期间的常量,没  有了存储与读内存的操作,使得它的效率也很高

宏定义的作用范围仅限于当前文件

默认状态下  const 对象只在文件中有效  当多个文件中出现 同名的const常量 那么意为着定义了不同的const对象

想在其他文件中使用一个const 常量 需要使用 extern 声明该常量

define 可以有const 完全替换   最好使用 const 常量


类似1234 的整数常量属于int 类型  long类型的常量以字母l或 L结尾,123456789L

如果整数太大无法用int 处理时 ,将会被当做long类型处理  

无符号常量以字母u或U结尾   后缀ul 或者UL 表示无符号的long类型

整型的八进制 十六进制表达 

带前缀0的整型为八进制  前缀为0X或0x,则表示它为16进制

字符常量:

一个字符常量是一个整数 ,书写时将一个字符放在单引号中‘x’

字符在机器字符集中的数值就是字符常量的值 可以参见ASIIC码值

比如 '0'  的值为48  

某些字符可以通过转义字符序列表示为字符和字符串常量   转义字符看起来像两个字符 一般由  ' '单引号+ \ +字符组成

例如  '\ooo'  表示任意的字节大小的位模式    其中  ooo 代表1-3 个八进制数字(0....7) 这种为模式还可以用'\xhh'

所以 \000 表示八进制   \xhh 表示16进制数

'\071' 表示一个字符 对应的只为  7*8^1+1*8^0 = 57

我们打印这些值 计算机自动帮我们转化为 10进制

‘\0’字符常量  表示值0的字符,也是空字符null  

常量表达式   仅仅由常量包含的表达式   这种表达式在编译的时候求值而不是在运行时求值

#define MAX 1000

char line[MAX+1];

字符串常量  也叫字符串字面值   是双引号括起来的字符序列

例如:“I am  a  string”

或者  ""  空字符串

双引号不是字符串的一部分 它只是用来限制字符串的   字符常量中使用的转移字符常量在字符串中仍然可以使用 

字符串常量就是字符数组   字符串内部使用一个空字符'\0'作为串的结尾

存储字符串的物理存储单元要比“”号括起来的字符 多一个 '\0' 的结束字 (在存储的时候编译器自动添加该'\0' 如果字符串结尾没有添加)

标准库中 strlen() 计算字符串长度是 空字符是不计入其中的'\0'

字符常量 与 字符串常量的区别

首先字符常量由' '  包裹   字符串常量由 " " 包裹

那么 'c' 与 "c"  里一个区别 'c' 存储是为单个字符  “c” 存储是 是两个字符  字符c 与 '\0'

枚举常量    是另外类型的常量 

组成    enum + 名称  + { 枚举值 } +; 

enum boolean {NO,YES};   boolean  中的 第一个值NO 为0    第二个值为 1;

如果没有特殊说明  那么 枚举{} 中的第一个值 为 0 第二个值为1   依次类推

enum months { JAN = 1,FEB,APR }  

第一个JAN 为1,FEB =2  APR =3  默认值根据第一个枚举值一次加1

不同枚举类型的名字必须互不相同   同一枚举中 的枚举值是可以重复的 

例如 : enum months { JAN = 1,FEB = 1,APR = 3 }

c语言中枚举类型如何使用

#include <stdio.h>

enum java{

    day,

    other,

    app

};

int main() {

     enum java ik = -12;       //这里 声明的枚举变量能不能取值在 枚举值之外 依赖于编译器是否对枚举类型值 进行严格的检验 

     printf("data----->%d",ik);

      printf("data----->%d",day);      //能够当常量使用   直接可以打印出 day的值   day初始值为0

     return 0;

}

一般情况下 我们需要将值取在  enum java{  } 范围内  以为这样是一定不会报错的

初始化枚举k 同时声明a 变量

enum k {day=1,day1,day2} a;

2.4 声明

所有变量都必须进行声明,然后才能使用,一个声明指定一种变量类型,后面跟的变量表可以包含一个或者多个该类型变量比如 int  a,b, c,d,e; 声明了 五个int类型的变量

他也等价于  int a; int b; int c; int d; int e;

初始化

如果变量名后面紧跟一个等号 以及一个表达式,该表达式就充当对变量进行初始化的初始化表达式

char  esc = '\\';

int i = 0;

int limit = MAXLINE+1;

float eps = 1.0e-5;

1.如果变量不是自动变量(局部变量),则只能进行一次初始化操作

2.同时初始化表达式只能是常量表达式

const 限定修饰符修饰的变量 ,其变量的值是不能修改的,如果限定符修饰的是数组 则数据中的所有值都不能被修改

const  double  e  =  2.718218245905;

const  char  msg[ ] = "warning:  ";

2.5 算术运算符

二元算术符包括: +  -  *  /  %(取模运运算符)  

表达式: x%y

的结果是 x 除以 y 的余数,当x能被y整除时,其值为0 

+   -   *   /   %  的计算优先级与我们课本上学习的优先级一致,从左到右 先乘除后加减

但是对于一元运算符    k++   k--   ++k   --k    他们的优先级是要高于 加减乘除

2.6 关系运算符与逻辑运算符

关系运算符包括下列几个运算符:

>                >=            <            <=

他们具有相同的优先级  优先级仅次于 ==  !=

关系运算符的优先级比算术运算符低    i< lim -1  等价于  i<( lim -1 )

逻辑运算符&&与||有一些较为特殊的属性,由&&与||连接的表达式按从左到右的顺序进行求值    

得到结果为真或假后立即停止计算

if(表达式1 || 表达式2){

          xxxxxxx;

}

如果表达式1 为真    表达式2 就不进行判断了  直接执行 xxxxx

if(表达式1 && 表达式2){

       xxxxxxxx;

}

YYYYYYY;

如果表达式1为假  表达式2 就不知行了   直接跳过if的{} 执行下面的代码 YYYYYY

优先级 :   (k++   k--   ++k   --k) 一元加减  > 乘除法 >  加减法  >  (==  !=)  >  ( >                >=            <            <= )  >  &&  > ||

c语言中 逻辑表达式的值为1 表明关系为真   如果值为0 则关系为假

2.7 类型转换

包括 自动转换 和 强制转换

自动转化: 一般来说  自动转换 是指把 比较窄的 操作数转换为 比较宽的操作数,

当然较宽的操作数也可以转换为较窄的操作数,这可能会造成精度的缺失,编译器会给我们发出警告,但这并不是非法的不可接受的

自动转换不需要我们人为转换,编译器自动转换

强制转换:(类型名)表达式      比如 char a = 90;   (int)a  + 1 =91;

如何正确理解强制转换:表达式首先被赋值给类型名指定的类型的某个值,然后在用该变量替换上述整条语句

(int )a -----》   int  w(强转类型的某个变量)  = (int)a (a转型后的值)

w+1 = 91;

a自身的值是不改变的  而是 编译器创建了一个新的变量来承接 a强转的值

2.8 自增运算符与自减运算符

int n =5;

1. x  =  n++; //先赋值 后 ++  

2. x  =  ++n; //先++ 后赋值

 1处的x值应该是  5

  2处的x值应该是 6

最终n的值都为 6

2.9 按位运算符 

&    按位与              ----------------》规则    1&1 =1   1&0 =0    0&0 = 0

|      按位或               ----------------》规则   1|1 = 1    1|0 = 1     0|0 =0

^     按位异或            ----------------》规则    1^1 =0    1^0=1     0^0 =0  相同为0 不同为1

<<   左移                   

 ---------------》规则    12<<3     左边转换为二进制 0000 1100  << 表示向左  3表示移动3位   0000 1100和面补3个0   得到 0110 0000  = 96  

相当于 12*2^3 =96  一位为2倍

>>   右移

--------------》规则    12>>3    左边转换为二进制 0000 1100 >> 表示向右 3表示移动3位    0000 1100  砍掉右3位  

得 0000 0001 = 1      相当于 12/2^3=1

~     按位求反(一元运算符) ------》规则    ~1 = 0   ~0 =1    

~12  = ~(0000 1100)= 1111 0011    

要这些符号干什么用?

位运算主要是控制二进制时使用,目的是节约内存,运算速度更快,对内存要求极为苛刻的地方常会使用

这里有一句顺口溜 :清零取反要用与    某位置1可用或

                                  若要取反和交换    轻轻松松用异或

那么 &与运算 的作用 来看看

1.清零特定位       对于0111 1111 我想是第3位(低位到高位算) 为0

0111  1111  &  1111  1011   ---》0111  1011

&的这个值只要 其他位为 1  特定位为0 即可

2.取某数中指定位     对于0111 1111 我想是第3位(低位到高位算) 是啥

0111 1111 & 0000 0100  ----》 0000 0100   

保证想要的位置为1 其他地方为0 即可

按位或 | 运算作用

将源操作数的特定位置转换为1  其他位置不变      0011 0111 想将第4位 0 转为1

0011 0111 | 0000 1000  ---》0011 1111  

保证转换位为1  其他位为0

3.异或运算作用 ^

1.使特定位取反    1变0   0变1 

0111 1111  想使第3位 取反为0                          0111 1011           

0000 0100   ----》                                               0000 0100

0111  1011                                                          0111 1111

只要特殊位置为 1  其他位置为0 即可

2.交换两个变量的值

a = 3 = 0011  b = 4 = 0100                           

1.a = a^b                    ---> 0011 ^ 0100 = 0111 =a

2.b=b^a                      ---->0100 ^ 0111 = 0011 =b

3.a = a^b =4               ----->0111 ^ 0011 = 0100 =a =4


2.10 赋值运算符 与 表达式

i = i+2;   ----->  i +=2;

+= 在运算中 就被成为赋值运算符

大多数二元运算符   (即有左 右两个操作数的运算符 比如+)都有一个相应的复制运算符 op=,op可以试一下这些运算符之一

+  -  *  /  %  <<   >>   &  ^ 

如果  expr1 和 expr2 时表达式  那么   

expre1  op= expr2 ; 

等价于   

expr1 = (expr1) op (expr2)

x *=y+1;   转化为

 x= x*(y+1);

赋值运算符的有点: 简便    但我个人认为 i +=2; 并没有 i=i+2;来的直观

2.11 条件表达式

if(a>b) 

     z=a;

else

    z=b;

用来求ab中的最大值 并将结果保存在z中

三元表达式  

expr1 ? expr2 : expr3;

表达式expr1    如果成立执行expr2     如果bu成立执行expr3

首先计算expr1的值是否不等于0     等于1计算expr2       等于0 计算expr3

z =  (a>b)? a : b    a是否大于b  如果大于b    则 z = a     如果不大于b   z = b;  z仍然去取 ab 间的最大值

关于类型转化  (n > 0)? f : n;

如果f 为 float 类型 n是int 类型   那么  表达式是float类型 , 它的类型与 n 无关

条件表达式的优点是:可以使代码更加简洁

2.12 运算符优先级与求职次序

&   ^  | 的优先级低于运算符== 与 !=的  

所以    if((x&MASK)== 0) 必须使用( )  括起来才行 不然就会先执行判断再执行&运算

c语言没有指定同一运算符中多个操作数的计算顺序(&&    ||     ?:   除外)

比如   x =  f( ) + g( );     f()  与  g()  这两个函数哪个先执行并不确定

c语言中也没有指定函数个参数的求值顺序

prinf(“%d%d\n”,++n,power(2,n));

对于先执行 ++n 还是先执行 powe(2,n) 这是不确定的 与 编译器有关系

那么避免的方式就是  

n++;

prinf(“%d%d\n”,n,power(2,n));

一种令人感觉不舒服的表达方式

a[i] = i++;   //这里存在一个问题 就是 i 使用的是 原来的值还是 i++ 后的值

这取决于编译器的抉择...

所以在我们编写代码时要尽量避免这样的代码设计,因为他存在极大的不确定性(在不同的编译器中表现不相同)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容