C语言基本数据类型、程序结构和运算符操作(有上网查阅过)

     这一节的内容比较基础,我就只做以下简单的记录,顺便把我在学习过程中遇到的易错点记录在前面。


1、选中代码按Tab键或Shift+Tab可以美化代码排版。
2、a==1是判断,a=1是赋值,不要搞混。
3、switch(判断条件表达式)必须是整型数。
4、屏幕输入可以用char Rcode  scanf("%hhd",&Rcode);。
5、for(;score!=0;) 类似于while(score!=0) ,不过要在前面先给score赋初值。



==========================设计C程序====================================




   程序 = 数据结构 + 算法




   数据结构:


C 语言 的数据
位和字节的区别参考网址:http://zhidao.baidu.com/link?url=gkEqEGF-rQOUJyUlNurDB5QH9xhRgwsaDWnVEucN8zHFNJXS16u7pkNO75HPEnGWt0CbzpgGrdwlsfJxuVALMK

   1、数据类型   --->  存储空间


       char      short       int        long     float     double   bool/_Bool(真值true 假值false, #include


       8bit      16bit    16/32bit     32bit     32bit     64bit     8bit  (0为假  非0为真)
       1BYTE     2BYTE   2BYTE/4BYTE   4BYTE     4BYTE     8BYTE    1BYTE




       运算符:  sizeof 




      有符号与无符号


signed   or  unsigned   ----> 最高位符号位: 0 正数   1 是负数


      存储形式

正数: 原码        char A = 5 ;     00000101  
负数: 补码        char B = -1;     ---> 绝对值 1  ----> 原码 ---> 00000001 ---> 反码 ---> 11111110  ---> +1(补码) --->  11111111(255)  


        
  2、 数据存储空间的定义(变量名)


下划线、字母、数字 ----> 不能以数字开头(常量)


C语言程序中,在同一作用域,不可以存在同名的变量




       定义一个变量,就是分配一块存储空间并给它命名;给一个变量赋值,就是把一个值存到了这块存储空间中。变量的定义和赋值也可以一步完成,这称为变量的初始化      (Initialization),例如要达到上面代码的效果也可以这样写:


        char firstletter = 'a';
        int hour = 11, minute = 59;


       初始化是一种特殊的变量定义语句,而不是一种赋值语句。




      提示:
尽量不用下划线作为变量名定义 (很多底层的插件库使用了下划线开始的命名)




       全局变量 与 局部变量


       全局变量(在函数体外定义): 


        作用域:从定义位置开始,直到文件结束


        生命周期:在未有同名的局部变量定义之前,其生命周期贯穿整个程序
                  如果遇到同名的局部变量定义,则生命周期在该函数中到局部变量定义时结束


        初始值:
未初始化时,默认由编译器赋值0 


存储空间:
  未初始化,不占用文件存储空间   ---> BSS  未初始化的数据段
  初始化,占用文件存储空间       ---> DATA 初始化的数据段




       局部变量(在函数体内定义)


        作用域:从定义位置开始,直到函数结束


        生命周期:从定义位置开始,直到函数结束


        初始值:
未初始化时,未知 (系统不清空内存),必须程序员自行初始化


存储空间:
  不占用文件存储空间,运行时分配




        C99规定的关键字有:


        auto  break  case  char  const  continue  default  do  double
        else  enum  extern  float  for  goto  if  inline  int  long  bool
        register  restrict  return  short  signed  sizeof  static  struct  switch  typedef
        union  unsigned  void  volatile  while  _Bool  _Complex  _Imaginary




   3、 数据存储空间分配



程序内存布局


readelf -a project   (readelf读取elf格式的文件)
nm  project


gdb 调试内存


A) 编译时加上支持debug选项  -g


 gcc xx.c -o xxx -g


B)  使用gdb调试运行程序


 gdb xxx


 gdb命令


l   ---> list 陈列代码(回车换页)


       b   ---> break 设置断点  ---->  b  行号


r   ---> run 运行到断点


n   ---> next 运行下一行


p   ---> print 打印内容  ----> p 变量名
                                         ----> p 变量名地址   --->  p  &value      p/x(以十六进制输出)




q   ---> quit  退出调试






C) 数据存储需要考虑内存对齐


字符型
短整型
整形
浮点型
双精度浮点




 -------------------可用以下方法测试---------------------------------


#include
#include


#define MAX 200


int value1 = 100;
int Arry_A1[100] = {1};
char no1 = 1;
int data1 = 2;
char num1 = 3;


int main(int argc,char *argv[])
{
int value2 = 100;
int Arry_A2[100] = {1};
char no2 = 1;
int data2 = 2;
char num2 = 3;


return 0;
}


------------------------------------------------------


 程序结构:


顺序:


默认


分支:


if 分支




if(判定条件)          ------> 满足则执行,if判断语句后面的首个表达式
满足则执行表达式1;
表达式2;   // 如果后面有else,则该语句将提示异常
else
不满足则执行表达式;




if(判定条件)          ------> 需要执行多个表达式,则需要使用花括弧进行复合语句声明
{
满足则执行表达式1;
满足则执行表达式2;
...
                }
else
{
不满足则执行表达式1;
不满足则执行表达式2;
...
                }



if(判定条件1)          ------> 需要执行多个表达式,则需要使用花括弧进行复合语句声明
{
满足则执行表达式1;
满足则执行表达式2;
...
                }
else if(判定条件2)
{
满足则执行表达式1;
满足则执行表达式2;
...
                }
else
{
不满足则执行表达式1;
不满足则执行表达式2;
...
                }




判定条件可以结合:


A && B   必须同时满足A跟B的条件
                 A || B   满足A或者B其中一个条件 


区别于 按位与&  按位或 |   ----> 将对应变量的值进行位操作后,根据所得结果进行条件判断


A  ==  B  A等于B    ---> 结果布尔型 真与假
A !=  B  A不等于B  ---> 结果布尔型 真与假


区别于 赋值=   ---->  将对应变量的值进行赋值操作后,根据所得结果进行条件判断
                




  switch(判断条件表达式)  //必须是整型数
{
case A :         //条件分支

语句1;
break;   //退出当前的分支判断
case B : 


语句2;
break;   //退出当前的分支判断
case C : 


语句3;
break;   //退出当前的分支判断
default:
printf(" Fail \n",sn);
break;
}              

  switch(判断条件表达式)  //必须是整型数
{
case A1 ... A2 :         //条件分支

语句1;
break;   //退出当前的分支判断
case B1 ... B2 : 


语句2;
break;   //退出当前的分支判断
case C1 ... C2 : 


语句3;
break;   //退出当前的分支判断
default:
printf(" Fail \n",sn);
break;
}  






设计一个程序,输入成绩: 0 - 100  ,根据成绩打印ABCD等级


A : 91 - 100
B : 81 - 90
C : 71 - 80
D : 0-59 



循环:




while(判定表达式)   判定表达式的值,为真则执行接下来的表达式语句     ----->  while(1)
表达式语句;




while(判定表达式)
{
表达式语句1;
表达式语句2;
        }




do{


表达式语句;


}while(判定表达式); //先执行语句,后判定表达式的值,为真则继续执行表达式语句








#include
#include






int main(int argc,char *argv[])
{


unsigned char  Rcode;
 

do{

scanf("%hhd",&Rcode);
switch(Rcode)
{
case 91 ... 100 :
printf(" A \n");
break;
case 81 ... 90 :
printf(" B \n");
break;
case 71 ... 80 :
printf(" C \n");
break;
case 0 ... 60 :
printf(" D \n");
break;
default:
printf(" .... !\n");
break;
}




}while(Rcode != 0)
  

return 0;
}












for(初始化语句1;判定条件表达式2;执行语句3)  //初始化语句1只执行一次,每次循环判定条件表达式2(遇到不满足则退出循环),完成循环后执行语句3
{
表达式语句1;
表达式语句2;
}


int i;
for(i=0;i<100;i++)   //执行100次  0-99
{
表达式语句1;
表达式语句2;
}


for(;;)  //死循环    ---->   while(1)   ---->  do{}while(1);






#include
#include






int main(int argc,char *argv[])
{


unsigned char  Rcode = 1; 

for(;Rcode != 0;){

scanf("%hhd",&Rcode);
switch(Rcode)
{
case 91 ... 100 :
printf(" A \n");
break;
case 81 ... 90 :
printf(" B \n");
break;
case 71 ... 80 :
printf(" C \n");
break;
case 0 ... 60 :
printf(" D \n");
break;
default:
printf(" .... !\n");
break;
}




}
  

return 0;
}








goto   入口   ---> 标号










#include
#include






int main(int argc,char *argv[])
{


unsigned char  Rcode;
 
Entry:

scanf("%hhd",&Rcode);
switch(Rcode)
{
case 91 ... 100 :
printf(" A \n");
break;
case 81 ... 90 :
printf(" B \n");
break;
case 71 ... 80 :
printf(" C \n");
break;
case 0 ... 60 :
printf(" D \n");
break;
default:
printf(" .... !\n");
break;
}


if(Rcode != 0)
     goto Entry;



return 0;
}




===============================================================================


运算符 (操作的是数据)


算术运算符  + - * 
/  整型数相除取整 
% 取余数
++ 自加  
i++   本表达式还是用i的原值,用完再自加1  后缀++
++i   本表达式先把i+1,在使用新值  前缀++

-- 自减  


自增自减的对象必须是变量!!!    int Value = 100;  Value++   ++Value   Value--   --Value

错误  : 500++
         const  int num = 500;  num++    //const 声明一个常变量,该变量的值在初始化时确定,不可更改
 #define  num   500     num++ 


++Value 简单的替换  Value = Value+1;





% 取模(取余)运算   ---->  参与运算的对象是整数

思考:  输入一个一千以内的数字,统计其百位,十位,个位的值是多少?

输入: 987




关系运算 
>  <  >=  <=


== 等于 用两个等号 建议写成 if( 1 == flag)
注意和赋值符号 = 区分

!= 不等于
 

逻辑运算 (表达式)
非0整数就是真 ,1 -1 都是真
整数0才为假  


&&
if(条件1 &&  条件2) 只要有一个条件为假就为假,两个条件为真才为真
||
if(条件1 ||  条件2) 只要有一个条件为真就是真,两个条件都假才为假
如果条件1成立了, 条件2不会执行也不会做判断

if(!条件1)   
条件1为真的时候,if(假),执行条件不成立
条件1为假的时候,if(真),执行条件成立




练习: 从键盘输入三个整型数, 比较大小,输出较大的一个




位运算  (参考网址:http://www.cnblogs.com/yezhenhan/archive/2011/11/06/2238452.html
char a = 0x7c;

~ 位取反  
  ~a   ===> ~ 0111 1100 -> 1000 0011




& 位与  都为1才是1,否则为0
  a & 0x10   ==>   0111 1100  提取标志位的开关
& 0001 0000
---------------------------------
0001 0000



|  位或  有1则为1,都为0才为0
  a | 0x01   ==>   0111 1100 
| 0000 0001  将标志位开关置1
---------------------------------
0111 1101




^ 位异或 相同为0,不同为1
                   b = 0xa4
  a ^ b   ==>   0111 1100 对标志位取反
^ 1010 0100
---------------------------------
1101 1000
再异或一个b ^ 1010 0100
-------------------------------- 
0111 1100  === > 和0x7c一致了, 常用两次异或的方式来实现变量值交换
             0111 1100     1010 0100
                 a  =   a ^ b          1101 1000      
b  =   a ^ b          0111 1100
a  =   a ^ b          1010 0100


 int  swap( int x ,int y)
          {
int temp;
temp = x;
x = y;
y = temp;
 }




>> 右移
<< 左移


               1
000000001  --->  000000010 
                                   <<1


000000001  --->  1000000000 
                                   <<8


-1
                          补码          整体右移,符号位补1
11111111   -->    11111111  --->     原值不变
  >>1
                          补码          整体左移,末位补0
11111111   -->    11111110  --->    
  <<1




a>>1  
对于正数和无符号数:高位补0;每移一位 对非0的数就是除二。
0111 1100 >> 1           0 0111 110  === 0011 1110
(124)   (62 / 0x3e)
对于负数: 高位补1 ;没有除二的关系
1010 1100 >> 1 1 1010 110 == 1101 0110
(0xac) (0xd6)
a << 1 
对于正数和无符号数:低位补0;如果移位后没有溢出才是乘二
(124)0111 1100 << 1 111 1100 0 === 1111 1000 (248)
  (124)0111 1100 << 2 11 1100 00 === 1111 0000 (240)溢出了,没有乘2关系
对于负数:
低位补0




数据右移: 相当于除以2的N次
数据左移: 相当于乘以2的N次




0x4 >> 2 = 0x1   =   4/2
0x1 << 2 = 0x4   =   1*4


intel X86 小端格式:


思考:


unsigned int Data = 0x12345678   ---> Addr  0x1000  0x1001  0x1002  0x1003

将Data的高八位的值提取赋值给 unsigned char 变量


延伸问题:

数据存储的大小端格式


大端格式: 高字节在低地址


小端格式: 低字节在低地址






其他
, 分隔表达式

= 赋值


三目运算符  ? : 
条件 ? 真则执行 : 假则执行 ;


sizeof 是个运算符
可以得到对应变量所占空间的大小
sizeof(int)  --- 取得一个int类型的所占空间大小
char c;
sizeof(c)  ---- 取得一个char类型的所占空间大小

你可能感兴趣的:(C语言,C语言)