c语言##用法大全,C语言使用相关汇总一

目录:

1、sizeof操作符

2、memset和memcpy

3、srand()与rand()函数

4、continue与break

5、++i和i++的区别

6、sizeof与strlen的区别与联系

7、指针

1)float (*p)(float)2)理解指向指针的指针 3)指针直接访问结构体

8、!与~的区别

9、sprintf字符串格式化命令

1)十进制打印2)十六进制打印3)注意一个符号扩展的问题4)控制浮点数打印格式5)实际应用

10、printf格式化字符串

1)Turbo

C2.0提供的格式化规定符2)一些特殊规定字符(C语言之转义字符\)

11、原码、反码、补码的理解

12、十六进制与BCD码相互转换

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

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

1、sizeof操作符

sizeof(类型说明符,数组名或表达式)

sizeof 变量名

作用:返回一个对象或类型所占的内存字节数

size是尺寸,of是……的。比如sizeof(int)就是int型在内存中的尺寸,也就是大小了。

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

2、memset和memcpy

memset表达式:memset(a,0,sizeof(a))

memset解释:将a中前sizeof(a)个字节用0替换并返回a。

memset作用:在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。

一定要记住如果要把一个char

a[20]清零,一定是 memset(a,0,20);

memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。

例子详见Zigbee学习/第三章基础实验/9.串口通讯-发送字符串:

void

main(void){CLKCONCMD &= ~0x40;  //设置系统时钟源为32MHZ晶振while(CLKCONSTA &

0x40); //等待晶振稳定为32MCLKCONCMD &= ~0x47;  //设置系统主时钟频率为32MHZInitUart(); //设置串口相关寄存器memset(TxData, 0,

TX_SIZE); //数据清0memcpy(TxData, TX_STRING, sizeof(TX_STRING));

//复制发送字符串到TxDatawhile(1){UartSendString(TxData, sizeof(TX_STRING));

//串口发送数据DelayMS(1000);  //延时}}

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

3、srand()与rand()函数

高级语言中带的随机数产生函数是伪随机数,伪随机数的意思是并不是真正意义上的随机数,而是通过某种运算或者在某种程度上产生随机的效果。由于计算机是一种图灵机,相同的输入必定产生相同的输出。所以,我们必须在C语言随机数的基础上加上某种比较随机的条件,简称种子。这样产生的随机数才会看起来比较随机,而不会每次运行程序的时候是一样的了。比如光用rand,产生5个随机数,每次运行程序可能结果都是一样的可能都是4

9 3 8 7 但是使用了当前系统时间为种子的话,每次运行结果就可能不一样了

假设第一次运行是5 1

0 3 9 第二次运行可能就是8 7 1 3 4

srand 初始化随机种子,rand

产生随机数。

rand函数

头文件:

定义函数:int rand(void)

函数功能:产生随机数

函数说明:因为rand的内部实现是用线性同余法做的,他不是真的随机数,只不过是因为其周期特别长,所以,在一定的范围里可看成是随机的。rand()会返回一随机数值,范围在0至RAND_MAX 间。在调用此函数产生随机数前,必须先利用srand()设好随机数种子,如果未设随机数种子,rand()在调用时会自动设随机数种子为1。

返回值: 返回0至RAND_MAX之间的随机整数值,RAND_MAX的范围最少是在32767之间(int),即双字节(16位数)。若用unsigned int 双字节是65535,四字节是4294967295的整数范围。且0-RAND_MAX每个数字被选中的机率是相同的。

rand()产生的是假随机数字,每次执行时是相同的。若要不同,以不同的值来初始化它.初始化的函数就是srand()。

函数举例:

#include“stdlib.h”#include

“stdio.h”int

main(void){int

i,j;for(i=0; i<10;

i++){j=1+(int)(10.0*rand()/(RAND_MAX+1.0));printf("%d ",j);}printf("\n");return

0;}

第一次运行结果: (每次运行结果都相同)

a4c26d1e5885305701be709a3d33442f.png

第二次运行结果:

a4c26d1e5885305701be709a3d33442f.png

srand函数

头文件: “stdlib.h”//修改为<>

定义函数:void srand (unsigned int seed);

函数说明:srand()用来设置rand()产生随机数时的随机数种子。参数seed必须是个整数,通常可以利用getpid()或time(0)的返回值来当做seed。如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。

函数举例:

#include

“stdlib.h”#include

“stdio.h”#include

“time.h”int

main(void){int

i,j;srand((int)time(NULL));for(i=0; i<10;

i++){j=1+(int)(10.0*rand()/(RAND_MAX+1.0));printf("%d ",j);}printf("\n");return

0;}

第一次运行结果:(每次运行结果都不同)

a4c26d1e5885305701be709a3d33442f.png

第二次运行结果:

a4c26d1e5885305701be709a3d33442f.png

例子:

求做一个模拟产生学生成绩的程序,成绩要求在四十到一百分之间,保留一位小数,而且小数位要是零或五程序的一部分是这样的while((n=400+rand()601)%5);score[i]=n/10.0;printf("%5.1d",score[i]");

rand() 能产生0-RAND

MAX之间的随机数,rand() % 601生成一个 0-600的数,则 n

从400-1000。在后面的计算成绩处,把 score =n

/ 10, 即 n的个位,变成SCORE的小数部分;又要求 小数 为0

或5, 所以 n 的个位必须是0或5,即能被5整除,n % 5 == 0;如果 n 不能被5整除,即 n%5

> 0;while((n=400+rand()601)%5);作用是产生一个400-1000的数,如果不能被5整除,则另产生一个数,直到该数能被5整除。PS:rand()601

产生的数并不是随机的。如0-RAND MAX=

700, 并假定产生RAND能产生0-700间的随机数,那么

rand()601后,原来0-600的数还是0-600,601-700的数变成 0-99,所以0-99

的机率要比其它数大一倍。

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

4、continue与break1)break可用于switch语句,表示跳出整个switch块,而continue则不能用于switch语句

--------------------------------------2)它们都可用于循环语句的循环体,所谓的区别也应该是它们对循环次数的影响不同。break用于立即退出当前循环,而continue仅跳过当次循环(本次循环体内不执行continue语句后的其它语句,但下次循环还会执行)。举例说明。int

i;int s =

0;

for (int i = 1; i <= 10;

i++){if (i == 6)

break;s +=

i;}上面的循环会因为break语句而在i=6时提前终止,这样s的最终值就是1+2+3+4+5如将break换成continueint

i;int s = 0;

for (int i = 1; i <= 10;

i++){if (i == 6)

continue;s +=

i;}当i=6时就不会将i累加到s中,s的最终值是1+2+3+4+5+7+8+9+10,唯独少一个6。

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

5、++i和i++的区别

在游戏中就i++是“我加你”;++i是“求人家加”。区别在于“应答与请求”。

在编程中i++和++i最终是一样的,不过在循环体中,i++是先取出i,再加1,++i先加后取。

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

6、sizeof与strlen的区别与联系

1)sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned

int类型。该类型保证能容纳实现所建立的最大对象的字节大小。

--------------------------------------2)sizeof是算符,strlen是函数。

--------------------------------------3)sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以''\0''结尾的。sizeof还可以用函数做参数,比如:short

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

sizeof(f()));输出的结果是sizeof(short),即2。

--------------------------------------4)数组做sizeof的参数不退化,传递给strlen就退化为指针了。

--------------------------------------5)大部分编译程序在编译的时候就把sizeof计算过了是类型或是变量的长度这就是sizeof(x)可以用来定义数组维数的原因char

str[20]="0123456789";int a=strlen(str);

//a=10;int b=sizeof(str);

//而b=20;

--------------------------------------6)strlen的结果要在运行的时候才能计算出来,时用来计算字符串的长度,不是类型占内存的大小。

--------------------------------------7)sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。

--------------------------------------8)当适用了于一个结构类型时或变量,

sizeof 返回实际的大小,当适用一静态地空间数组, sizeof

归还全部数组的尺寸。sizeof

操作符不能返回动态地被分派了的数组或外部的数组的尺寸

--------------------------------------9)数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如:fun(char

[8])fun(char [])都等价于 fun(char

*)在C++里参数传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小如果想在函数内知道数组的大小, 需要这样做:进入函数后用memcpy拷贝出来,长度由另一个形参传进去fun(unsiged char

*p1, int len){unsigned char* buf

= new unsigned char[len+1]memcpy(buf, p1,

len);}我们能常在用到 sizeof 和

strlen 的时候,通常是计算字符串数组的长度。看了上面的详细解释,发现两者的使用还是有区别的,从这个例子可以看得很清楚:char

str[20]="0123456789";int a=strlen(str); //a=10;

>>>> strlen 计算字符串的长度,以结束符 0x00

为字符串结束。int b=sizeof(str); //而b=20;

>>>> sizeof 计算的则是分配的数组 str[20]

所占的内存空间的大小,不受里面存储的内容改变。上面是对静态数组处理的结果,如果是对指针,结果就不一样了char* ss =

"0123456789";sizeof(ss) 结果 4

===》ss是指向字符串常量的字符指针,sizeof

获得的是一个指针的之所占的空间,应该是长整型的,所以是4sizeof(*ss) 结果 1 ===》*ss是第一个字符

其实就是获得了字符串的第一位'0' 所占的内存空间,是char类型的,占了 1

strlen(ss)= 10 >>>>

如果要获得这个字符串的长度,则一定要使用 strlen。

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

7、指针

1)float (*p)(float)

声明了一个指针p,p指向一个具有一个float类型形参的函数,这个函数返回一个float型值。或者说是:声明了一个指向具有一个float类型形参、返回类型为float的函数的指针p。

本人认为后一种说法正规些,但很绕口;第一种好理解,但略欠规范。

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

2)理解指向指针的指针

int i = 5, j = 6, k=7;

int *ip1 = &i, *ip2 =

&j;

int **ipp = &ip1;

那么现在指针 ipp 指向了 ip1,ip1 指向了 i。*ipp 就是 ip1,**ipp 就是 i,或者说是

5。我们可以用我们熟悉的盒子箭头图来描述,像这样:

a4c26d1e5885305701be709a3d33442f.png

如果我们接着这么写:

*ipp = ip2;(或者*ipp

=&j)

我们就改变了 ipp 指向的那个指针(也就是 ip1),现在它指向 ip2

所指的地方。也就是说(ip1)现在它指向了 j:

a4c26d1e5885305701be709a3d33442f.png

我的疑问是:为什么在第二幅图里,ipp 还是指向 ip1 而不是

ip2?

让我们暂时忘掉那些关于指针的各种类比,指针实际上存放的是内存的地址。

&

符号的意思是取地址,也就是返回一个对象在内存中的地址。

*  符号的意思是取得一个指针所指向的对象。

也就是如果一个指针保存着一个内存地址,那么它就返回在那个地址的对象。

所以

*ipp = ip2;(*ipp就是 ip1)实际上是把 ipp 存的地址所对应的对象,也就是 ip1 取到,然后把 ip2 存的值赋值给

ip1,也就是 j 的地址。简单点就是:&取址,*取值。

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

3)指针直接访问结构体

http://bbs.csdn.net/topics/390485528

有一个结构体typedef struct{

unsigned char month;

unsigned char day;

unsigned char hour;

}date;

date Time;现在想把Time结构体放在单片机的RAM区域,单片机在进入休眠模式下时间数据不丢失,NEC单片机是_no_init date Time @0x200位置上,可是现在我用松下单片机平台没有办法,不知道哪位大侠可以用指针直接#define LCD5W (*(volatile unsigned int*)0xfa40)的方式指导一下?现在主要是结构体怎么用指针直接访问?如下:

unsigned char array[3];

array=((array*)0xfa40);

struct date *p;

p=((struct date*)0xfa40);

p.day=11; //给日期的赋值

p.month=11; //给月份的赋值

struct date *p;

对这个类型进行声明的时候,要加入防止编译器自动对齐的编译选项

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

8、!与~的区别

! 这个是“逻辑反”,凡是a的值不为0的,!a

就等于0;如果a的值为0,则 !a 的值为1;

~ 这个是“按位取反”。

比如:

int a = 2 ; 用二进制表示为00 00 00 10; 则!a =

0;

~a = 11 11 11 01

(按位取反后的二进制结果,此结果为补码形式)

求其源码为 :10 00 00 11

即为-3,所以~a 的结果为-3。

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

9、sprintf字符串格式化命令

函数原型:int sprintf( char *buffer, const char

*format [, argument] … );

主要功能是把格式化的数据写入某个字符串中。sprintf

是个变参函数,最常见的应用之一莫过于把整数打印到字符串中。

1)十进制打印

//把整数123 打印成一个字符串保存在s 中。

sprintf(s, "%d", 123);

//产生"123"

可以指定宽度,不足的左边补空格:

sprintf(s, "MM", 123, 4567); //产生:"

1234567"

当然也可以左对齐:

sprintf(s, "%-4dM", 123, 4567); //产生:"123

4567"

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

2)十六进制打印

sprintf(s, "%8x", 4567); //小写16 进制,宽度占8

个位置,右对齐

sprintf(s, "%-8X", 4568); //大写16 进制,宽度占8

个位置,左对齐

这样,一个整数的十六进制字符串就很容易得到,但我们在打印十六进制内容时,通常想要一种左边补0

的等宽格式,那该怎么做呢?很简单,在表示宽度的数字前面加个0 就可以了。

sprintf(s, "X", 4567);

//产生:"000011D7"

上面以”%d”进行的10 进制打印同样也可以使用这种左边补0

的方式。

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

3)注意一个符号扩展的问题

比如,假如我们想打印短整数(short)-1

的内存十六进制表示形式,在Win32 平台上,一个short 型占2

个字节,所以我们自然希望用4 个十六进制数字来打印它:

short si = -1;

sprintf(s, "X", si);

产生“FFFFFFFF”,怎么回事?因为sprintf

是个变参函数,除了前面两个参数之外,后面的参数都不是类型安全的,函数更没有办法仅仅通过一个“%X”就能得知当初函数调用前参数压栈时被压进来的到底是个4

字节的整数还是个2 字节的短整数,所以采取了统一4 字节的处理方式,导致参数压栈时做了符号扩展,扩展成了32 位的整数-1,打印时4

个位置不够了,就把32 位整数-1 的8 位十六进制都打印出来了。

如果你想看si 的本来面目,那么就应该让编译器做0

扩展而不是符号扩展(扩展时二进制左边补0 而不是补符号位):

sprintf(s, "X", (unsigned

short)si);

就可以了。或者:

unsigned short si = -1;

sprintf(s, "X", si);

sprintf 和printf 还可以按8 进制打印整数字符串,使用”%o”。注意8

进制和16 进制都不会打印出负数,都是无符号的,实际上也就是变量的内部编码的直接的16 进制或8

进制表示。

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

4)控制浮点数打印格式

浮点数的打印和格式控制是sprintf

的又一大常用功能,浮点数使用格式符”%f”控制,默认保留小数点后6 位数字,比如:

sprintf(s, "%f", 3.1415926);

//产生"3.141593"

但有时我们希望自己控制打印的宽度和小数位数,这时就应该使用:”%m.nf”格式,其中m

表示打印的宽度,n 表示小数点后的位数。比如:

sprintf(s, ".3f", 3.1415626); //产生:"

3.142"

sprintf(s, "%-10.3f", 3.1415626);

//产生:"3.142 "

sprintf(s, "%.3f", 3.1415626);

//不指定总宽度,产生:"3.142"

注意一个问题,你猜

int i = 100;

sprintf(s, "%.2f", i);

会打出什么东东来?“100.00”?对吗?自己试试就知道了,同时也试试下面这个:

sprintf(s, "%.2f",

(double)i);

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

5)实际应用

(1)

该函数包含在stdio.h的头文件中。

#include

"stdio.h"

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

(2)

sprintf与printf函数的区别

sprintf和平时我们常用的printf函数的功能很相似。

sprintf函数打印到字符串中。

printf函数打印输出到屏幕上。

sprintf函数在我们完成其他数据类型转换成字符串类型的操作中应用广泛。

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

(3) sprintf函数的格式:int sprintf( char *buffer, const char *format [, argument,...] );除了前两个参数固定外,可选参数可以是任意个。buffer是字符数组名;format是格式化字符串(像:"=%6.2f%#x%o",%与#合用时,自动在十六进制数前面加上0x)。只要在printf中可以使用的格式化字符串,在sprintf都可以使用。其中的格式化字符串是此函数的精华。

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

(4)

可以控制精度

char str[20];double f=14.309948;sprintf(str,"%6.2f",f);--------------------

(5)

可以将多个数值数据连接起来。

char str[20];

int a=20984,b=48090;sprintf(str,"=m",a,b);str[]="20984 48090"--------------------

(6)

可以将多个字符串连接成字符串

char str[20];char s1={'A','B','C'};char s2={'T','Y','x'};sprintf(str,"%.3s%.3s",s1,s2);

%m.n在字符串的输出中,m表示宽度,字符串共占的列数;n表示实际的字符数。%m.n在浮点数中,m也表示宽度;n表示小数的位数。

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

(7) 可以动态指定,需要截取的字符数char s1={'A','B','C'};char s2={'T','Y','x'};sprintf(str,"%.*s%.*s",2,s1,3,s2);sprintf(s, "%*.*f", 10, 2, 3.1415926);

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

(8)

可以打印出i的地址sprintf(s, "%p", &i);

上面的语句相当于sprintf(s, "%0*x", 2 * sizeof(void *), &i);

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

(9)

sprintf的返回值是字符数组中字符的个数,即字符串的长度,不用在调用strlen(s)求字符串的长度。

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

(10)

VC++测试

#include

"stdio.h"

int

main(void)

{

char

s[40];

sprintf(s,"%s%d%c","test",1,'2');

//把结果输出到指定的字符串中

printf("%s\n",s);

}a4c26d1e5885305701be709a3d33442f.png

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

10、printf格式化字符串

1)Turbo

C2.0提供的格式化规定符

符号

作用

%d

十进制有符号整数

%u

十进制无符号整数

%f

浮点数

%s

字符串

%c

单个字符

%p

指针的值

%e

指数形式的浮点数

%x, %X

无符号以十六进制表示的整数

%o

无符号以八进制表示的整数

%g

自动选择合适的表示法

说明:

(1)

可以在"%"和字母之间插进数字表示最大场宽。

例如: = 表示输出3位整型数,

不够3位右对齐。

%9.2f 表示输出场宽为9的浮点数,

其中小数位为2, 整数位为6,小数点占一位, 不够9位右对齐。

%8s 表示输出8个字符的字符串,

不够8个字符右对齐。如果字符串的长度、或整型数位数超过说明的场宽, 将按其实际长度输出。但对浮点数,

若整数部分位数超过了说明的整数位宽度, 将按实际整数位输出;若小数部分位数超过了说明的小数位宽度,

则按说明的宽度以四舍五入输出。

另外, 若想在输出值前加一些0,

就应在场宽项前加个0。

例如: d 表示在输出一个小于4位的数值时,

将在前面补0使其总宽度为4位。

如果用浮点数表示字符或整型量的输出格式,

小数点后的数字代表最大宽度,小数点前的数字代表最小宽度。

例如: %6.9s

表示显示一个长度不小于6且不大于9的字符串。若大于9, 则第9个字符以后的内容将被删除。

(2) 可以在"%"和字母之间加小写字母l,

表示输出的是长型数。

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

例如: %ld

表示输出long整数

%lf

表示输出double浮点数

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

(3) 可以控制输出左对齐或右对齐,

即在"%"和字母之间加入一个"-" 号可说明输出为左对齐, 否则为右对齐。

例如: %-7d

表示输出7位整数左对齐

%-10s

表示输出10个字符左对齐

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

2)一些特殊规定字符(C语言之转义字符\)

字符

作用

\n

换行

\f

清屏并换页

\r

回车

\t

Tab符

讨论:例如串口接收单片机发送的16进制的数据,则我们要这样接收:

byte

buf[56];

recv(comm->handle,buf);

buf[strlen(buf)]=0;//打上结束标志

//将接收的数字转化为16进制串

char *pstr=new

char[256];

byte

*pb=&buf[0];

while(!pb)

sprintf(pstr++,"x",*pb++);

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

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

11、原码、反码、补码的理解

1)讨论原码之前首先需要了解两个概念:机器数和真值。

a.一个数值在计算机中的二进制表示形式,就称为这个数值的机器数。机器数是带符号的,其中最高位是符号位,1表示负数,0表示正数。比如,

1100 0000就是-64的机器数,即在计算机中的二进制表示形式。同样的,0100

0000就是64的机器数。

b.真值:因为第一位是符号位,所以机器数的形式值并不是真正的数值。机器数中除符号位之外的二进制串表示的才是真值(当然要加上符号才是真正的值)。

2)对于一个数,在计算机中如何表示呢?这就涉及到对其的编码问题,原码、反码、补码就是计算机中对数的三种编码方式。

a.原码就类似于上述机器数的定义方式,一个数的原码就是符号位加上真值的绝对值,即第一位表示符号位,其余位表示值。

-64的原码就是:1100

0000

+64的原码就是:0100

0000

计算机中只有加法器没有减法器,减法运算是转化为加法来进行的。以下举例说明使用原码进行加减法的过程:

64+64=0100 0000 + 0100 0000=0 1000

0000=128

64-64=64+(-64)=0100 0000+ 1100 0000=1 0000

0000=-0

1-1=1+(-1)=0000 0001 + 1000 0001=1000 0010=-2

计算错误

原码的表示方式存在的问题:

①存在+0、-0的情况(0000

1000)

②进行减法运算的时候,有些情况会计算出错(1-1=-2)

b.为了解决减法运算会出错的情况,引入了反码的编码形式。对于正数,其反码与原码完全相同(原码表示下,加法是正确的,所以正数的反码保持与原码相同即可),而负数的反码是保持原码的符号位不变,所有位依次取反,就得到反码。以下分别给出+1,-1的反码形式,并使用反码进行减法运算:

+1=[0000

0001]

-1=[1111

1110]

1-1=1+(-1)=0000 0001+1111 1110=1111

1111,结果是反码形式,需要将其转化为原码形式才能得到确切值,原码是1000

0000=-0。

但是反码对于0的表示方法任然是有两种,这里以4

bit为例:

0000

+0

1111

-0

c.采用了反码的形式之后,减法运算的结果是正确了的。不过对于0还是存在+0、-0的情况。为了解决这个问题,补码出现了。正数的补码就是其原码自身,负数的补码是在其反码的基础上+1。还是以+1、-1的补码形式说明:

+1=0000

0001

-1=1111

1111

1-1=1+(-1)=1 0000 0000 丢掉最高位=0000

0000=0(正数的补码和原码相同,所以是0)。

使用补码不仅解决了+0、-0的情况,而且还可以多表示一个最低数。下图以4

bit为例,说明了原码、反码、补码的”进化过程“:

a4c26d1e5885305701be709a3d33442f.png

以下讨论原码和补码两种编码形式下,表示的取值范围。从上图易知,分别使用原码和补码,4

bits的取值范围是:

原码:[-7,7](包含+0、-0)

补码:[-8,7](只有一个0)

两种编码方式都表示了16个数值,只是原码有+0、-0之分,而补码只有一个0(+0),没有-0,因此可多表示一个最小值-8。-8的补码推倒过程如下:

-1-7=1111+1001=1000=-8,所以-8的补码是1000,其没有对应的反码和原码。

而8

bits的范围是:

补码:[-128,127] 1000

0000=-128

因此对于n

bits分别以原码、补表示的数值取值范围是:

原码:[-(2^(n-1)-1),2^(n-1)-1]  有1个符号位,所以是n-1

补码:[-(2^(n-1)),2^(n-1)-1]

3)计算机中是以补码的形式表示数值的(起码是整数),编程语言也是以补码的形式表示数值的。

根据负数的原码求补码有一个比较简单的计算方法:符号位保持不变。从最低位开始,直至遇到第一个1之前,之前的所有位保持不变。遇到第一个1之后,保留这个1,以后按位取反直到符号位后一位。

根据负数的补码求其原码的方法:符号位保持不变,其余各位取反,然后再整个数加1。

另外,两个二进制数相减,等于加上减数保持符号位不变,取反

+1,即使加上其补码。

4)计算机只有加法器,将减法转化成加法,是利用了数学中的同余概念。

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

12、十六进制与BCD码相互转换

十六进制转为BCD码好理解,有问题的是BCD码转为十六进制数;Hex2Bcd:0x3F的BCD码是多少?正确答案:99,或者0x630x3F=63,再加0x,->0x63,

再把0x63转为99(0x63=99)1、如果要表示为十六进制,则转换为10进制数,前面加0x符号;(十六进制表示)2、如果要表示为十进制,则先转换为10进制数,前面加0x符号,再把加上符号的。

十六进制数转为十进制数;(十进制表示) 如果一个数为0x38,则BCD码为86。Bcd2Hex:(注:)1、如果这个数是16进制表示的,把0x符号去掉,当成10进制数直接转换为16进制数即可;(前提是这个16进制表示的数的任何一位不能大于9,也就是说不能出现A、B、C、D、E、F)如:0x999,去掉0x,->999,再转为十六进制数为0x3E72、如果这个数是十进制表示的,先把这个数转换为16进制数,再把0x符号去掉,当成十进制数,再转化为十六进制数即可;(注:这个数要在一定范围内,才行,如999转换为十六进制为0x3E7,把0x去掉,3E7不在10进制表示范围内,)上面说的是在一定范围内的数,对于不在一定范围内的数怎么转?刚开始还真不好理解,是因为学校教给我们的数学规则限制了我们的思维,对于一个数3E7,当成10进制怎么理解?还是按十进制来,个位、十位、百位...,只不过现在十位上的数是14,BCD码999转换为十六进制是多少?正确答案:447,或者0x1BF,为什么?想不通...转换过程:999转为十六进制,->0x3E7,33*10+E=44(3*10+E)*10+7=447

也就相当于0x3E7当成10进制理解,则是3*100+E*10+7,简单不?注:一个十六进制数转为BCD码,但这个BCD码再转为十六进制数,不等于这个数;如:如果一个数为0x999,Hex2Bcd(0x999)=0x2547(9543),Bcd2Hex(0x2547)=0x9F3(2547),而一个BCD码的数可以转为十六进制数,这个十六进制数可以反转为BCD码,可能等于这个数(这个数是十六进制表示,且每一位的数字在0~9之间);也可能不等于这个数。如:Bcd2Hex(0x999)=0x3E7(999),Hex2Bcd(0x3E7)=2457(0x999)(等于)Bcd2Hex(0x9F3)=0x41D(1053),Hex2Bcd(0x41D)=0x1053(4179)Bcd2Hex(999)=0x1BF(447),Hex2Bcd(0x1BF)=0x447(1095)(不等于)Bcd2Hex(0x447)=0x1BF(447),Hex2Bcd(0x1BF)=0x447(1095)(等于)结论:16进制转BCD不可逆,BCD转16进制有可能可逆。

unsignedcharBCD2HEX(unsignedcharbcd_data)//BCD转为HEX子程序

{

unsigned chartemp;

temp=(bcd_data/16*10 + bcd_data);

returntemp;

}

unsigned charHEX2BCD(unsignedcharhex_data)//HEX转为BCD子程序

{

unsigned chartemp;

temp=(hex_data/10*16 + hex_data);

returntemp;

}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值