嵌入式C语言基础-02

1.变量在计算机中的存储形式

计算机中表示的数字都是机器数,而机器数的存储都是用真值的原码的补码的形式存储的(要区分原码和真值)。其中注意两点

[1]正数的原码反码补码都是一致的。

[2]负数的反码由原码符号位不变,其他位取反得到。负数的补码由该负数的反码加1得到。

例:67=0b0000 0000 0000 0000 0000 0000 0100 0011 真值

0000 0000 0000 0000 0000 0000 0100 0011 原码

0000 0000 0000 0000 0000 0000 0100 0011 反码

0000 0000 0000 0000 0000 0000 0100 0011 补码

0x0000 0043

-67=-0b0000 0000 0000 0000 0000 0000 0100 0011 真值

1000 0000 0000 0000 0000 0000 0100 0011 原码

1111 1111 1111 1111 1111 1111 1011 1100 反码

1111 1111 1111 1111 1111 1111 1011 1101 补码

0xffff ffbd

2.printf()函数格式控制

变量类型

控制格式

用法示例

char

%c(字符)

printf("%c\n",a);

short

%d(整数)

printf("%d\n",a);

int

%d(十进制整数)

printf("%d\n",a);

int

%#o(八进制整数,#显示八进制前缀0)

printf("%#o\n",a);

int

%#x(十六进制整数,#显示十六进制前缀0x)

printf("%#x\n",a);

unsigned int

%u(无符号,十进制显示数据)

printf("%u\n",a);

long

%ld,%#lo,%#lx

printf("%ld\n",a);

long long

%lld,%#llo,%#llx

printf("%lld\n",a);

float

%f(显示小数点后6位,显示小数点后两位%.2f)

printf("%.2f\n",a);

double

%lf(显示小数点后6位,显示小数点后两位%.2lf)

printf("%lf\n",a);

注:%4.6f小数点前面的数控制对齐

# include<stdio.h>
int main(){
	char ch='\101';
	  printf("ch=%c\n",ch);//输出字符
    printf("ch=%d\n",ch);//输出对应十进制整数
    printf("ch=%#o\n",ch);//输出对应八进制
    printf("ch=%#x\n",ch);//输出对应十六进制
	return 0;
}
# include<stdio.h>
int main(){
	int a=67,b=-67;
	printf("a=%d,b=%d\n",a,b);
	printf("a=%#o,b=%#o\n",a,b);
	printf("a=%#x,b=%#x\n",a,b);
	return 0;
//当输出十进制是换转换成原码显示
}

需要注意的是,用十六进制给变量赋值相当于定义的是该变量的补码,也就是说,赋值量是该变量的补码。如下例:

#include <iostream>
int main(int argc, char** argv) {
	int a=0xfffffffff;
	printf("%d,%#x\n",a,a);
	return 0;
	}

4.浮点数

1. 浮点数存储原理

类型

符号位

指数位

小数位

float(单精度6-7位)

1

8

23

double(双精度15-16位)

1

11

52

指数位又称阶码,阶码用移码表示,该标准为IEEE754标准

此部分只需会把二进制小数转化为十进制小数即可

2. 浮点数比较

不可以直接用==对浮点数进行比较,因为浮点数是有精度的,在一定范围内进行比较。若精度为小数点后6位,则表达式3.1415923==3.141592为真,但真实情况显然不是,如何比较浮点数大小呢?应把误差控制在一定范围,在一定范围内值相等。如:|3.1415916-x|<0.000001为真,就可以认为他们是相等的。

5.C语言运算符

口诀:单算移关与,异或逻条赋值,逗号

1. 单目运算符

+,-,++,--,&,*,~,!

  1. --和++
#include <stdio.h>

int main(int argc, const char *argv[])
{
    int a=5;
    int b;

    b = a++;
    //先执行a++,但因为++放在了变量之后属于后操作,
    //相当于在运算当前表达式的时候a的值没有加上去,
    //运算完之后a的值才进行了自加上
    printf("a = %d,b = %d\n",a,b); //b=5,a=6

    a = 5;
    b = ++a;
    //++放在变量之前先运算a++,结果是6,然后将它赋值给b变量                            
    printf("a = %d,b = %d\n",a,b);//b=6,a=6

    a = 5;
    b = -a--;
    //因为--放在了变量后,所以当前这句话执行的时候不会减去
    //b = -5,然后a=a-1;a的结果是4
    printf("a = %d,b = %d\n",a,b);
    //a = 4,b = -5;

    return 0;
}
  1. &,*

#include <stdio.h>

int main(int argc, const char *argv[])
{
    int a = 20; 

    printf("&a = %p,*&a = %d\n",&a,*&a);    
    //&a:表示获取a的地址,打印地址的控制格式是%p
    //*&a:表示获取&a中的值,*后必须是地址
    return 0;
}
  1. ~

按位取反运算符是在补码上进行的 ,且把补码全部取反

#include <iostream>

int main(int argc, char** argv) {
	int a=12;
	printf("前:a=%#x\n",a);
	a=~a;
	printf("后:~a=%#x\n",a);
	printf("后:~a=%d\n",a);
	return 0;
	//按位取反运算符是在补码上进行的 
}
#include <iostream>

int main(int argc, char** argv) {
	char a=-5;
	//原码:1000 0101
	//反码:1111 1010
	//补码: 1111 1011
	//~a:   0000 0100 
	printf("before:a=%#x\n",a);
	//before:a=0xfffffffb
 	//这里多出的f是打印的结果,不会加入到运算当中,补充规则为补充最高位 
	a=~a;
	printf("after:~a=%#x\n",a);
	//after:~a=0x4
	return 0;
	}
  1. !(偏向逻辑上的否定)
#include <iostream>

int main(int argc, char** argv) {
	int a=10,b=-12;
	char c='1';

	printf("a=%d b=%d c=%d\n",a,b,c);
	//a=0 b=0 c=0
	//可以得出结论,对非零的值非运算得到的是0;
	//取非非零即1; 
	return 0;
	}

2. 算术运算符

+,-,*,/%

  1. / 除运算
#include <iostream>

int main(int argc, char** argv) {
	int a=12/5;
	float b=12/5;
	printf("a=%d b=%f\n",a,b);
	//a=2 b=2.000000
	//操作时都是整数,结果也是整数
  
	int c=12/5.0;
	float d=12/5.0;
	printf("c=%d d=%f\n",c,d);
	//c=2 d=2.400000
	//操作数一方为小数,结果正确 
  
	float e=12.0/5.0;
	printf("e=%f\n",e);
	//e=2.400000
	 
	return 0;
	}
  1. % 取余

操作数两边都要是整数

练习:

    1. 使用三杯水的思想交换a和b(需要定义c变量)

定义第三个变量

    1. 使用+、-运算符交换a和b的值(不需要定义其他变量)

运用模的思想,相加后可以得到两个数的模,用模减去一个数就得到另一个数。

    1. 有一个三位数请使用算术运算符获取它的个十百位

百位:这个数模100得到百位

十位:这个数模10得到十位

个位:模10即可得到

3. 移位运算符

左移<< 右移>> 是在补码的基础上进行运算的。

无符号数左移:高位舍弃,低位补零

无符号数右移:低位舍弃,高位补零

有符号数左移:符号位不变,高位舍弃,低位补零

有符号数右移:符号位不变,低位舍弃,高位补符号值

可以简单的理解为:左移乘2,右移除2,所以可知符号位左右移不变号。

#include <iostream>

int main(int argc, char** argv) {
	int i=-1;
	printf("bef:i=%#x\n",i);
	//bef:i=0xffffffff
	i=i<<1;
	printf("aft:i=%#x\n",i);
	//aft:i=0xfffffffe

	int j=-2;
	printf("bef:j=%#x\n",j);
	j=j>>1;
	//bef:j=0xfffffffe
	printf("aft:j=%#x\n",j);
	//aft:j=0xffffffff
	return 0;
	}

练习:

-21 >>3

原码:0x800015

反码:0xffffea

补码:0xffffeb

右移:0xfffffd===>原码0x800003

4. 关系运算符

>(大于) <(小于) ==(等于) !=(不等于) >=(大于等于) <= (小于等于)

比较两个数的关系结果只可能是真1或者假0,判断两个数是否相等是两个等号

#include <stdio.h>

int main(int argc, const char *argv[])
{
    int a,b,c;
    a = 5;
    b = 6;

    c = (a>b);
    //将a>b的真或者假赋值给c变量,c变量的值只可能是0或者1
    printf("c = %d\n",c);

    char ch = 'R';
    a = (ch >= 'A');
    b = (ch <= 'Z');
    //如果a和b都为1,说明ch在A~Z之间
    printf("a = %d,b = %d\n",a,b);

    c = (a == 2);
    //判断a是否等于2,如果等于c的值是1,否则c的值是0.
    printf("c = %d\n",c);

    return 0;                                                                                               
}

5. 按位与运算符

  • 与运算符&是二元操作符,取地址操作数是一元操作符
  • 与运算符也是基于补码进行逐个bit位进行计算的
  • 0和任何数相与都为0
  • 1和任何数相与都为任何数

示例:

  1. 5 & 10结果:0b0101 & 0b1010 = 0b0000
  2. -13 & 17-13的补码:0xFFFF FFF3 & 17的补码:0x0000 0011

结果是:0x11或者17

练习:

  1. 有一个int类型的a变量,将a的bit3位清零,其他位不变

a = a & (~(1<<3));

  1. 有一个int类型的a变量,将a的bit17和bit29位清零,其他位不变

a = a &(~(1<<17));

a = a &(~(1<<29));

a = a &(~((1<<17)|(1<<29));

  1. 有一个int类型的a变量,将a的bit8-bit15位清零,其他位不变

a = a &(~(0xff<8));

【注】置位指的是把某位置为1,复位是指恢复原值。

6. 异或运算符

^:异或运算符是按照比特位进行的(相同为假,相异真)

0和0异或结果是0

0和1异或结果是1

1和1异或结果是0

#include <iostream>

int main(int argc, char** argv) {
	int a=7,b=12;
	a=a^b;
	b=a^b;
	a=a^b;
	printf("a=%d b=%d\n",a,b);
	return 0;
	}

7. 按位或运算符

|:按位或运算

0和任何数相或都为任何数

1和任何数相或都为1

例如:

13 | 21

0b0 1101 | 0b1 0101 = 0b1 1101 = 29

练习:

  1. 有一个int类型的a变量,将a的bit3位置位,其他位不变

a = a | (1<<3);

  1. 有一个int类型的a变量,将a的bit7,bit19-bit21位置位,其他位不变

a = a | ((1<<7) | (7<<19));

  1. 有一个unsigned char类型的变量a,它里面存的数值是0b1001,1100,要求将a变量的bit7和bit0交换,bit6和bit1交换,以此类推。使用运算符完成比特位的互换。

交换相邻的位

交换相邻的两位

交换相邻的四位

#include <stdio.h>

int main(int argc, const char *argv[])
{
    unsigned char a = 0b10011100;

    a = ((a & 0x55)<< 1)|((a & 0xaa)>>1);
    a = ((a & 0x33)<< 2)|((a & 0xcc)>>2);
    a = (a>>4)|(a<<4);
    //0b0011 1001=0x39
    printf("a = %#x\n",a);
/* 
    unsigned int a = 0x00672c80;
    a = ((a & 0x55555555)<< 1)|((a & 0xaaaaaaaa)>>1);
    a = ((a & 0x33333333)<< 2)|((a & 0xcccccccc)>>2);
    a = ((a & 0x0f0f0f0f)<< 4)|((a & 0xf0f0f0f0)>>4);
    a = ((a & 0x00ff00ff)<< 8)|((a & 0xff00ff00)>>8);
    a = (a>>16) |(a<<16);
    //0x0134e600         
    printf("a = %#x\n",a);
*/
    return 0;
}

8. 逻辑运算符

&&:逻辑与

表达式1 && 表达式2

表达式1为假,表达式2不参与运算,整个表达式都为假

表达式1为真,整个表达式的真假取决于表达式2

例如:

ch = 'a';

ch >= 'A' && ch <='Z'

#include <stdio.h>

int main(int argc, const char *argv[])
{
    int a=10,b=2,c=3,d,e;

    e = (a && (d=b+c));
    printf("d = %d,e = %d\n",d,e);//d=5,e=1

    a = 0;
    d = 0;
    e = (a && (d=b+c));
    printf("d = %d,e = %d\n",d,e);//d=0,e=0
    
    a=3;
    b=-2;
    c=2;
    e = (a && (d=b+c));
    printf("d = %d,e = %d\n",d,e);//d=0,e=0                                                                 
    
    return 0;
}

||:逻辑或

表达式1 || 表达式2

表达式1为真,表达式2不参与运算,整个表达式都为真

表达式1为假,整个表达式的真假取决于表达式2

例如:

ch='a';

ch<'A' || ch >'Z'

#include <stdio.h>

int main(int argc, const char *argv[])
{
    int a=0,b=1,c=2,d,e;
    
    e = (a || (d=b+c));
    printf("d = %d,e = %d\n",d,e);//d=3,e=1

    d = 0;
    e = ((a+c) || (d=b+c));
    printf("d = %d,e = %d\n",d,e);//d=0,e=1                              
    return 0;
}

练习:

  1. 判断year是平年还是闰年?

((如果能被4整除,不能被100整除)或者(能被400整除的年))就是闰年

result = (((year%4==0)&&(year%100!=0))||(year%400==0))如果result是1就是闰年,否则就是平年。

9. 条件运算符

条件运算符又叫三目运算符

表达式1?表达式2:表达式3;

如果表达式1为真,整个表达式的结果是表达式2

如果表达式1为假,整表达式的结果是表达式3

#include <stdio.h>
int main(int argc, const char *argv[])
{
    int a,b,max;
    a=321;                                                               
    b=679;
    
    //这是获取a和b中最大值的表达式
    max = a>b?a:b;

    printf("max = %d\n",max);
    return 0;
}

10. 赋值运算符

= += -= *= /= %= <<== >>== &= |= ^=

a = b;将b的值赋值给a

a+=b;等价于a = a+b;

a<<=b;等价于a = a<<b;

11. 逗号运算符

result = (表达式1,表达式2,...,表达式n)

#include <stdio.h>

int main(int argc, const char *argv[])
{
    int a=1,b=2,c=3,d,e;
    //       b=4   a=7   d=7+4+3 = 14
    e = (a+c,b=c+a,a=c+b,d=a+b+c);

    printf("e = %d\n",e); //e=14

    printf("%d\n",(3,4,5));//结果是5                                     
    return 0;
}

6.运算符运算优先级和结合方向

同种运算符看运算方向,不同种看优先级

1. 运算优先级

优先级从高到低:单算移关与,异或逻条赋,逗号

2. 运算结合方向

结合方向:说的是同种运算符的运算方向

单条赋从右向左运算,其余的全是从左向右运算

例1:

a = b = c;将c赋值给b在赋值给a.

例2:

int a=3,b=2,c=1,d;

d = (a > b > c);先运算a>b为真1,在判断1>c为假,所以d就是0

d = 0

3. 练习

  1. 练习1a=1,b=2,cc = a+++b; 在编写程序的时候尽量不要这样写,编译器解析的规则是a++ +b
  2. 练习2执行下列程序段后,变量a,b,c的值分别是
    int x=10,y=9;
    int a,b,c;
    a=(--x==y++)?--x:y; //x=9, y=9,当这句话执行完之后y就变成了10,a = x=8,y=10
    b=x; //b=8,x=9
    c=y; //c=10,y=10

A、a=9,b=9,c=9 B、a=9,b=10,c=9

C、a=1,b=11,c=10 D、a=8,b=8,c=10

7.变量类型转换

1. 强制类型转换

在编写c程序的时候,经常会涉及到不同类型变量间的赋值,此时就需要使用强制类型转换。

语法格式 = (类型)表达式;

例1:

int a=0x123456;

char b;

b = (char)a; 这里的b = 0x56

例2:

float pi=3.14159;

int t;

t = (int)pi;这里的t = 3

例3:

int a=2,b=3;

float c;

c = (float)a/b;

2. 隐式类型转换

在c语言的表达式中,如果运算的类型不同按照如下规则进行隐式类型转换

char =>unsigned char =>short=>unsigned short=>int=>unsigned int=>long =>unsigned long=>float=>double

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值