c语言小数按整数输出会输出什么用了%1.f还是输出整数

用C语言编程如何实现保留几位小数并对最后一位四舍五入呀?
问题描述:
用C语言编程如何实现保留几位小数并对最后一位四舍五入呀?
问题解答:
很简单,假如你有一个float型变量a,其值为1.23456,而你只想保留三位小数,也就是希望得到1.235,只需要令:a = (int)(1000.0 * a + 0.5) / 1000.0即可.如果要保留四位小数,就把1000都换成10000,依次类推.
我来回答:
剩余:2000字
img class="ikqb_img" src="http://d.hiphotos.baidu.com/zhidao/wh%3D600%2C800/sign=0c49d04b36fae6cd0ce1ac/cadd54cd2cde9c82486a.jpg"
#include&&stdio.h&int&main(){&for&(int&i&=&100;&i&&&1000;&i++)&&if&((i&%&nbs
printf("%g\n",(int)(n*100+.5)/100.0);.n是实数.
#include int main(){int a,b;printf("输入两个数字(例如2,3):");scanf("%d,%d",&a,&b);if (b==0){printf("被除数不能为0");return 0;}printf("商:%0.2f\n",a/b);printf("余数:%d\n",a%b);re
double rd(double h){double h100=h*100;if (h100-floor(h100)>=0.5) h100=(floor(h100)+1)/100;else h100=(floor(h100))/100;return h100;}
#include float fun ( float h ){long i=h*1000;\x09if(i%10
除到小数点后两位
保留一位小数是60.24=60.2;60.25=60.3;你那个应该是精确到个位,61.24=61;要是精确到百位是100问个小学三四年级的应该都会
没有区别.保留两位小数就是精确到百分位,只是说法不太一样.
假设速度是v,时间是t的话原本vt=3000,t=3000/v现在速度提高5%,那么速度变成(1+5%)v=1.05v那么时间变成t=v=2857.14/v那么时间缩短了:(3000/v-2857.14/v)/(3000/v)=4.8%
保留一位:0.5,两位0.50,三位0.500
不知道你说的是在什么场合下:如果是在EXCEL表格中的话,只要是设置为数值类型时保留一位小数应该是0.5(系统自己会四舍五入),如果保留两位应该是0.48,而三位则是0.480.至于其它软件和程序中我就不知道了.
最同一个意思
原始表格为sheet1,处理结果为sheet2,如图然后全部拖拽使用公式,即可输出希望帮得到你咯~
个位和十分位
不一样,保留两位小数是5.45,精确到百分位是5.455
也许感兴趣的知识教你用C语言实现一个虚拟机|CDN加速
海外高防服务器|帮助中心|新闻动态|高防CDN_美国高防服务器_免备案高防空间_网站防攻击_美国高防服务器_集群盾
教你用C语言实现一个虚拟机
作者:admin  来源:http://www.jqcdn.com/   更新时间:  阅读数:
如何用C语言实现一个虚拟机?
·&&&&&&&&&&&&&&&
使用的编译器类型:我正在使用的是clang,它是轻量级编译器,但你可以使用任何现代编译器;
·&&&&&&&&&&&&&&&
文本编辑器:我建议当编写C语言时,通过IDE编辑文本编辑器,我将使用E
·&&&&&&&&&&&&&&&
基本的编程知识:比如什么是变量,流量控制,函数,结构等;
·&&&&&&&&&&&&&&&
GNU Make:GNU Make主要用于自动化构建可执行程序(库文件),这样我们就不需要在终端中一遍又一遍地编写相同的命令来编译代码。Make的功能包括:自动化构建和安装;增量编译及自动更新;适用于多语言,比如c/c++、java、php等;支持自定义功能扩展(只要有意义,都是可以放到makefile中)。
以下是你应该编写虚拟机的一些原因:
1.你需要更深入地了解计算机的工作方式,本文将帮助你了解你的计算机在较低级别的环境中是如何运行工作的?而虚拟机则提供了一个非常简单的抽象层;
2.顺便了解一些虚拟机的知识;
3.深入了解一下编程语言的工作原理,现在的各种语言都针对虚拟机,比如JVM,Lua VM,FaceBook 的 Hip—Hop VM(PHP/Hack)等。
指令集会相对简单,我将简要介绍一下,例如如何从寄存器中移动值或跳转到其他指令。
假设我们的虚拟机有一组寄存器:A,B,C,D,E和F,且这些都是通用寄存器,这意味着它们可以用于存储任何东西。这与专用寄存器不同,例如在x86上,ip, flag, ds, …程序是只读指令集。如果虚拟机是一个基于栈的虚拟机,这意味着它有一个我们可以压栈和弹出值的栈,另外,该虚拟机还有一些我们也可以使用的寄存器。基于栈的虚拟机比基于寄存器的虚拟机实现起来要简单得多。
本文转载于:http://www.jqcdn.com/& &
本文关键词:& &
不清楚自己该使用什么防御产品和我们专业的安全专员聊聊
使用集群盾云防御时,遇到任何问题,都可以直接致电支持专线。
400-655-8875在c语言中printf(“ b = %1f , %5.41f ” , b , b); printf_百度知道
在c语言中printf(“ b = %1f , %5.41f ” , b , b); printf
在c语言中printf(“b=%1f,%5.41f”,b,b);printf(&d=%2c&,d);其中“%1f”和“%5.41f”和“d=%2c”是什么意思?...
在c语言中printf(“ b = %1f , %5.41f ” , b , b);printf(& d = %2c & , d );其中“%1f”和“%5.41f”和“d=%2c”是什么意思?
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
来自知道合伙人认证行家
互联网类行家
采纳数:11391
获赞数:13979
08年毕业,一直从事计算机行业,从基层做起。有较强的实践操作能力。
刚才你的描述不清楚,现在可以了%1f -- 你用了数字1,不是字母L的小写.这个1的意思是输出/入总位数为1位float a,b;scanf(&%1f %f&,&a,&b);输入12.345 67.8a 读 1, b读 2.345, 而后的67.8留在输入缓冲器里.printf(&%f %f&,a,b);1..345000输出用%1f,宽度不够,程序会自动加宽,输出结果与%f 一样.
为你推荐:
其他类似问题
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。浅析嵌入式C语言高级用法
1、内存管理
我们需要知道&&变量,其实是内存地址的一个抽像名字罢了。在静态编译的程序中,所有的变量名都会在编译时被转成内存地址。机器是不知道我们取的名字的,只知道地址。&
内存的使用时程序设计中需要考虑的重要因素之一,这不仅由于系统内存是有限的(尤其在嵌入式系统中),而且内存分配也会直接影响到程序的效率。因此,我们要对C语言中的内存管理,有个系统的了解。&
在C语言中,定义了4个内存区间:代码区;全局变量和静态变量区;局部变量区即栈区;动态存储区,即堆区;具体如下:&
1&栈区(stack)& 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2&堆区(heap)&& 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。&
3&全局区(静态区)(stac)&全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的 另一块区域。 - 程序结束后由系统释放。&
4&常量区&&常量字符串就是放在这里的。 程序结束后由系统释放。&
5&程序代码区&存放函数体的二进制代码。&我们来看张图:&
首先我们要知道,源代码编译成程序,程序是放在硬盘上的,而非内存里!只有执行时才会被调用到内存中!我们来看看程序结构,ELF是是的主要可执行文件格式。ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Prog header table)、节(Section)和节头表(Section header table)。具体如下:&
1&Program header描述的是一个段在文件中的位置、大小以及它被放进内存后所在的位置和大小。即要加载的信息;&
2&Sections保存着object 文件的信息,从连接角度看:包括指令,数据,符号表,重定位信息等等。在图中,我们可以看到Sections中包括:&
xt 文本结 存放指令;&
rodata 数据结&
data 数据结 可读可写;&
3&Section头表(section header table)包含了描述文件sections的信息。每个section在这个表中有一个入口;每个入口给出了该section的名字,大小,等等信息。相当于 索引!&
而程序被加载到内存里面,又是如何分布的呢?我们看看上图中:
1正文和初始化的数据和未初始化的数据就是我们所说的数据段,正文即代码段;&
2&正文段上面是常量区,常量区上面是全局变量和静态变量区,二者占据的就是初始化的数据和未初始化的数据那部分;&
3&再上面就是堆,动态存储区,这里是上增长;&
4&堆上面是栈,存放的是局部变量,就是局部变量所在代码块执行完毕后,这块内存会被释放,这里栈区是下增长;&
5&命令行参数就是001之类的,环境变量什么的前面的文章已经讲过,有兴趣的可以去看看。&
我们知道,内存分为动态内存和静态内存,我们先讲静态内存。
1.1静态内存
存储模型决定了一个变量的内存分配方式和访问特性,在C语言中主要有三个维度来决定:存储时期 、作用域 、链接。&
1、存储时期&存储时期:变量在内存中的保留时间(生命周期)&存储时期分为两种情况,关键是看变量在程序执行过程中会不会被系统自动回收掉。&
1) 静态存储时期 Static&在程序执行过程中一旦分配就不会被自动回收。&通常来说,任何不在函数级别代码块内定义的变量。&无论是否在代码块内,只要采用static关键字修饰的变量。&
2) 自动存储时期 Automatic&除了静态存储以外的变量都是自动存储时期的,或者说只要是在代码块内定义的非static的变量,系统会肚脐自动非配和释放内存;&
2、作用域&作用域:一个变量在定义该变量的自身文件中的可见性(访问或者引用)&在C语言中,一共有3中作用域:&1) 代码块作用域&在代码块中定义的变量都具有该代码的作用域。从这个变量定义地方开始,到这个代码块结束,该变量是可见的;&
2) 函数原型作用域&出现在函数原型中的变量,都具有函数原型作用域,函数原型作用域从变量定义处一直到原型声明的末尾。&
3) 文件作用域&一个在所有函数之外定义的变量具有文件作用域,具有文件作用域的变量从它的定义处到包含该定义的文件结尾处都是可见的;&
3、链接&链接:一个变量在组成程序的所有文件中的可见性(访问或者引用);&C语言中一共有三种不同的链接:&1) 外部链接&如果一个变量在组成一个程序的所有文件中的任何位置都可以被访问,则称该变量支持外部链接;&
2) 内部链接&如果一个变量只可以在定义其自身的文件中的任何位置被访问,则称该变量支持内部链接。&
3) 空链接&如果一个变量只是被定义其自身的当前代码块所私有,不能被程序的其他部分所访问,则成该变量支持空链接&
我们来看一个代码示例:
#include &stdio.h& &
int&a = 0;// 全局初始化区&&&&
char&*p1;&//全局未初始化区&&&&
int&mn() &&&
int&b;&//b在栈区 &
char&s[] = &abc&;&//栈 &&&
char&*p2; //p2在栈区 &
char&*p3 = &123456&;&//在常量区,p3在栈上。&&&&
static&int&c =0;&//全局(静态)初始化区&&
p1 = (char&*)malloc(10); &&&
p2 = (char&*)malloc(20); &//分配得来得10和20字节的区域就在堆区。&&&&
strcpy(p1, &123456&);&//放在常量区,编译器可能会将它与p3所指向的&123456&优化成一个地方。&&&&
1.2动态内存
当程序运行到需要一个动态分配的变量时,必须向系统申请取得堆中的一块所需大小的存储空间,用于存储该变量。当不在使用该变量时,也就是它的生命结束时,要显示释放它所占用的存储空间,这样系统就能对该空间 进行再次分配,做到重复使用有线的资源。下面介绍动态内存申请和释放的函数。
1.2.1 malloc 函数
malloc函数原型:
size是需要动态申请的内存的字节数。若申请成功,函数返回申请到的内存的起始地址,若申请失败,返回NULL。我们看下面这个例子:
使用该函数时,有下面几点要注意:&1)只关心申请内存的大小;&2)申请的是一块连续的内存。记得一定要写出错判断;&3)显示初始化。即我们不知这块内存中有什么东西,要对其清零;
1.2.2 free函数
在堆上分配的额内存,需要用free函数显示释放,函数原型如下:
使用free(),也有下面几点要注意:&1)必须提供内存的起始地址;&调用该函数时,必须提供内存的起始地址,不能够提供部分地址,释放内存中的一部分是不允许的。&
2)malloc和free配对使用;&编译器不负责动态内存的释放,需要程序员显示释放。因此,malloc与free是配对使用的,避免内存泄漏。
p = NULL是必须的,因为虽然这块内存被释放了,但是p仍指向这块内存,避免下次对p的误操作;&
3)不允许重复释放&因为这块内存被释放后,可能已另分配,这块区域被别人占用,如果再次释放,会造成数据丢失;
1.2.3 其它相关函数
calloc函数分配内存需要考虑存储位置的类型。&realloc函数可以调整一段动态分配内存的大小
1.3堆和栈比较
1)申请方式&
stack: 由系统自动分配。 例如,声明在函数中一个局部变量 系统自动在栈中为b开辟空间&heap: 需要程序员自己申请,并指明大小,在c中malloc函数 ,如p1 = (char *)malloc(10);&
2)申请后系统的响应&栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。&
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。&
3)申请大小的限制&栈:栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。&堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。&
4)申请效率的比较&栈由系统自动分配,速度较快。但程序员是无法控制的。&堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。&
5)堆和栈中的存储内容&栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。 当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。&
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。&
6)存取效率的比较
char&s1[] = &aaaaaaaaaaaaaaa&;
char&*s2 = &bbbbbbbbbbbbbbbbb&; &
aaaaaaaaaaa是在运行时刻赋值的;&而bbbbbbbbbbb是在编译时就确定的;&但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。&比如:
对应的汇编代码
第一种在读取时直接就把字符串中的元素读到cl中,而第二种则要先把指针值读到edx中,再根据edx读取字符,显然慢了。&
7)最后总结&堆和栈的区别可以用如下的比喻来看出:&
栈就像我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。&
堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。
2、内存对齐
2.1 #pragma pack(n) 对齐用法详解
1.什么是对齐,以及为什么要对齐&现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。&
对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况, 但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为 32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。这也是空间和时间的博弈。&
2.对齐的实现&通常,我们写程序的时候,不需要考虑对齐问题。编译器会替我们选择时候目标平台的对齐策略。当然,我们也可以通知给编译器传递预编译指令而改变对指定数据的对齐方法。 但是,正因为我们一般不需要关心这个问题,所以因为编辑器对数据存放做了对齐,而我们不了解的话,常常会对一些问题感到迷惑。最常见的就是struct数据结构的sizeof结果,出乎意料。为此,我们需要对对齐算法所了解。&
作用:&指定结构体、联合以及类成员的&语法:
#pragma pack( [show] | [push | pop] [, identifier], n )
说明:&1&pack提供数据声明级别的控制,对定义不起作用;&2&调用pack时不指定参数,n将被设成默认值;&3&一旦改变数据类型的alignment,直接效果就是占用memory的减少,但是performance会下降;
3.语法具体分析&1&show:可选参数;显示当前packing aligment的字节数,以warning message的形式被显示;&
2&push:可选参数;将当前指定的packing alignment数值进行压栈操作,这里的栈是the internal comler stack,同时设置当前的packing alignment为n;如果n没有指定,则将当前的packing alignment数值压栈;&
3&pop:可选参数;从internal compiler stack中删除最顶端的record;如果没有指定n,则当前栈顶record即为新的packing alignment数值;如果指定了n,则n将成为新的packing aligment数值;如果指定了identifier,则internal compiler stack中的record都将被pop直到identifier被找到,然后pop出identitier,同时设置packing alignment数值为当前栈顶的record;如果指定的identifier并不存在于internal compiler stack,则pop操作被忽略;&
4&identifier:可选参数;当同push一起使用时,赋予当前被压入栈中的record一个名称;当同pop一起使用时,从internal compiler stack中pop出所有的record直到identifier被pop出,如果identifier没有被找到,则忽略pop操作;&5&n:可选参数;指定packing的数值,以字节为单位;缺省数值是8,合法的数值分别是1、2、4、8、16。&
4.重要规则&
1&复杂类型中各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个类型的地址相同;&
2&每个成员分别对齐,即每个成员按自己的方式对齐,并最小化长度;规则就是每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数中较小的一个对齐;&
3&结构、联合或者类的数据成员,第一个放在偏移为0的地方;以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度两个中比较小的那个进行;也就是说,当#pragma pack指定的值等于或者超过所有数据成员长度的时候,这个指定值的大小将不产生任何效果;&
4&复杂类型(如结构)整体的对齐&注意是&整体&&是按照结构体中长度最大的数据成员和#pragma pack指定值之间较小的那个值进行;这样在成员是复杂类型时,可以最小化长度;&
5&结构整体长度的计算必须取所用过的所有对齐参数的整数倍,不够补空字节;也就是取所用过的所有对齐参数中最大的那个值的整数倍,因为对齐参数都是2的n次方;这样在处理数组时可以保证每一项都边界对齐;&
5.对齐的算法&由于各个平台和编译器的不同,现以本人使用的gcc veion 3.2.2编译器(32位x86平台)为例子,来讨论编译器对struct数据结构中的各成员如何进行对齐的。&
在相同的对齐方式下,结构体内部数据定义的顺序不同,结构体整体占据内存空间也不同,如下:&
设结构体如下定义:
结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个。所以A用到的空间应该是7字节。但是因为编译器要对数据成员在空间上进行对齐。所以使用sizeof(strcut A)值为8。&现在把该结构体调整成员变量的顺序。
这时候同样是总共7个字节的变量,但是sizeof(struct B)的值却是12。&下面我们使用预编译指令#progma pack (value)来告诉编译器,使用我们指定的对齐值来取代缺省的。
sizeof(struct C)值是8。&修改对齐值为1:
sizeof(struct D)值为7。
对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。&
6.四个概念值&1&数据类型自身的对齐值:就是上面交代的基本数据类型的自身对齐值。
2&指定对齐值:#progma pack (value)时的指定对齐值value。&
3&结构体或者类的自身对齐值:其数据成员中自身对齐值最大的那个值。&
4&数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。 有了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值,最重要。有效对齐N,就是表示&对齐在N上&,也就是说该数据的&存放起始地址%N=0&. 而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是数据结构的起始地址。结构体的成员变量要对齐排放,结构体本身也要根 据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数倍,结合下面例子理解)。这样就不能理解上面的几个例子的值了。&
例子分析:&分析例子B;
假设B从地址空间0x0000开始排放。该例子中没有定义指定对齐值,在笔者环境下,该值默认为4。&
第一个成员变量b的自身对齐值是1,比指定或者默认指定对齐值4小,所以其有效对齐值为1,所以其存放地址0x0000符合0x.&
第二个成员变量a,其自身对齐值为4,所以有效对齐值也为4,所以只能存放在起始地址为0x7这四个连续的字节空间中,符合0x, 且紧靠第一个变量。&
第三个变量c,自身对齐值为2,所以有效对齐值也是2,可以存放在0x9&这两个字节空间中,符合0x。所以从0x9存放的都是B内容。再看数据结构B的自身对齐值为其变量中最大对齐值(这里是b)所以就是4,所以结构体的有效对齐值也是4。根据结构体圆整的要求,0x0=10字节,(10+2)%4=0。所以0x0000A到0x000B也为结构体B所占用。故B从0xB共有12个字节,sizeof(struct B)=12;&
同理,分析上面例子C:
第一个变量b的自身对齐值为1,指定对齐值为2,所以,其有效对齐值为1,假设C从0x0000开始,那么b存放在0x0000,符合0x;&
第二个变量,自身对齐值为4,指定对齐值为2,所以有效对齐值为2,所以顺序存放在0x3、0x5四个连续字节中,符合0x。
第三个变量c的自身对齐值为2,所以有效对齐值为2,顺序存放在0x7中,符合0x。所以从0x07共八字节存放的是C的变量。&
又C的自身对齐值为4,所以C的有效对齐值为2。又8%2=0,C只占用0x7的八个字节。所以sizeof(struct C)=8.
9.2.2字节对齐对程序的影响
先让我们看几个例子吧(32bit,x86环境,gcc编译器):&设结构体如下定义:
现在已知32位机器上各种数据类型的长度如下:&char:1(有符号无符号同)&short:2(有符号无符号同)&int:4(有符号无符号同)&long:4(有符号无符号同)&float:4 double:8&那么上面两个结构大小如何呢?&结果是:&sizeof(strcut A)值为8&sizeof(struct B)的值却是12&
结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个,B也一样;按理说A,B大小应该都是7字节。之所以出现上面的结果是因为编译器要对数据成员在空间上进行对齐。上面是按照编译器的默认设置进行对齐的结果,那么我们是不是可以改变编译器的这种默认对齐设置呢,当然可以.例如:
sizeof(struct C)值是8。&修改对齐值为1:
sizeof(struct D)值为7。&后面我们再讲解#pragma pack()的作用.
2.3修改编译器的默认对齐值
1&在VC IDE中,可以这样修改:[Project]|[Settings],c/选项卡Category的Code Generation选项的Struct Member Alignment中修改,默认是8字节。&2&在编码时,可以这样动态修改:#pragma pack .注意:是pragma而不是progma.&
如果在编程的时候要考虑节约空间的话,那么我们只需要假定结构的首地址是0,然后各个变量按照上面的原则进行排列即可,基本的原则就是把结构中的变量按照 类型大小从小到大声明,尽量减少中间的填补空间.还有一种就是为了以空间换取时间的效率,我们显示的进行填补空间进行对齐,比如:有一种使用空间换时间做 法是显式的插入reserved成员:
reserved成员对我们的程序没有什么意义,它只是起到填补空间以达到字节对齐的目的,当然即使不加这个成员通常编译器也会给我们自动填补对齐,我们自己加上它只是起到显式的提醒作用.
2.4字节对齐可能带来的隐患
代码中关于对齐的隐患,很多是隐式的。比如在强制类型转换的时候。例如:
最后两句代码,从奇数边界去访问unsignedshort型变量,显然不符合对齐的规定。&
在x86上,类似的操作只会影响效率,但是在MIPS或者sparc上,可能就是一个error,因为它们要求必须字节对齐.&
如果出现对齐或者赋值问题首先查看&1). 编译器的big little端设置&2). 看这种体系本身是否支持非对齐访问&3). 如果支持看设置了对齐与否,如果没有则看访问时需要加某些特殊的修饰来标志其特殊访问操作。&下的对齐处理&f DUI0067D_ADS1_2_CompLib type qulifiers&有部分摘自ARM编译器文档对齐部分对齐的使用:&
1.__align(num)&这个用于修改最高级别对象的字节边界。在汇编中使用LDRD或者STRD时就要用到此命令__align(8)进行修饰限制。来保证数据对象是相应对齐。这个修饰对象的命令最大是8个字节限制,可以让2字节的对象进行4字节对齐,但是不能让4字节的对象2字节对齐。 __align是存储类修改,他只修饰最高级类型对象不能用于结构或者函数对象。&
2.__packed&__packed是进行一字节对齐&l 不能对packed的对象进行对齐&l 所有对象的读写访问都进行非对齐访问&l float及包含float的结构联合及未用__packed的对象将不能字节对齐&l __packed对局部整形变量无影响&
l 强制由unpacked对象向packed对象转化是未定义,整形指针可以合法定&
义为packed。&__packed int* //__packed int 则没有意义
2.5对齐或非对齐读写访问带来问题
__packed struct&STRUCT_TEST
{char&a;int&b;char&c;
//定义如下结构此时b的起始地址一定是不对齐的,在栈中访问b可能有问题,因为栈上数据肯定是对齐访问[from CL]
//将下面变量定义成全局静态不在栈上
static&char*static&struct&STRUCT_TESTvoid&Main()
__packed int*&//此时定义成__packed来修饰当前q指向为非对齐的数据地址下面的访问则可以
p = (char*)&a; &&&&&&&&&
q = (int*)(p+1); &&&&&
*q = 0x; /* &&
得到赋值的汇编指令很清楚
ldr &&&&&r5,0x ; = #0x
[0xe1a00005] &&mov &&&&&r0,r5
[0xeb0000b0] &&bl &&&&&&__rt_uwrite4&//在此处调用一个写4byte的操作函数
[0xe5c10000] &&strb &&&&r0,[r1,#0] &&//函数进行4次strb操作然后返回保证了数据正确的访问
[0xe1a02420] &&mov &&&&&r2,r0,lsr #8
[0xe5c12001] &&strb &&&&r2,[r1,#1]
[0xe1a02820] &&mov &&&&&r2,r0,lsr #16
[0xe5c12002] &&strb &&&&r2,[r1,#2]
[0xe1a02c20] &&mov &&&&&r2,r0,lsr #24
[0xe5c12003] &&strb &&&&r2,[r1,#3]
[0xe1a0f00e] &&mov &&&&&pc,r14
如果q没有加__packed修饰则汇编出来指令是这样直接会导致奇地址处访问失败
[0xe59f2018] &&ldr &&&&&r2,0x ; = #0x
[0xe5812000] &&str &&&&&r2,[r1,#0]
//这样可以很清楚的看到非对齐访问是如何产生错误的
//以及如何消除非对齐访问带来问题
//也可以看到非对齐访问和对齐访问的指令差异导致效率问题
原文标题:很多人不了解的嵌入式 C 高级用法
文章出处:【微信号:wujianying_danpianji,微信公众号:单片机精讲吴鉴鹰】欢迎添加关注!文章转载请注明出处。
发布评论请先
SEGGER销售与市场营销总监Harald Schober补充道:“我们很高兴能够与UltraSoC....
近年来,随着信息家电、手持设备、无线设备的迅速发展,人们对嵌入式系统的需求逐渐增多,要求也越来越高....
状态监测与故障诊断技术是现代工业技术发展的产物,已发展到了以专家系统、神经网络和模糊分析等理论为基....
在“物联网”与“工业4.0”等应用浪潮涌动下,电子元器件的技术创新与市场规模也激流勇进。万物互联实现....
本文转自网络。
事情的发展是这样的:
几年前,我在任职某公司开发部经理期间,带着数十个人。我的原则是:制定准则、给...
写单片机程序也是程序,也要遵循写软件的一些基本原则,不是为了完成功能那么简单。我看过的所有的C语言单片机书籍基本都不注重...
UltraSoC日前宣布:公司已与SEGGER达成合作伙伴关系,以在UltraSoC集成化的系统级芯....
全新卓越的闪迪嵌入式闪存驱动器使智能手机能够实现1Gb每秒或更高的即时数据传输速度及RAW格式图像捕....
RAD(快速应用程序开发)是一种高效的软件开发形式,可以让用户在极短的时间里创建一个图形化的用户界....
具有嵌入式处理器的平台FPGA提供很大的灵活性、集成度和高性能。目前,在单个可编程逻辑器件中开发极....
在日益激烈的竞争中,系统的开发周期显得尤为重要,但开发时间与系统安全性、可靠性又有一定冲突,如果仍....
针对目前嵌入式教学实验平台资源的不足,为了使理论与实践相结合、软硬件联系更紧密,设计提出了一套Cor....
嵌入式系统的目的是提供一个以多任务和网络为信心,易于开发的复杂数字系统。从数字技术和信息技术的角度看....
这样定义全局数组不对吗??
右边那张图是key函数需要引用的,这样定义可以吗?
1.在最近的嵌入式工作中很多都是学习FreeRTOS系统,由于只是会对RTOS的接口进行调用,但是很....
EPYC 3000系列面向网络、工业、存储、边缘计算等领域 ,从血缘上讲与面向数据中心的EPYC 7....
在视频监控系统数字化、网络化、高清化、智能化的发展趋势过程中,网络视频监控系统的市场需求日益提升,高....
在保障装备装备时,训练使用、检修、加装改造等记录用传统手工操作,管理人员必须对进装备名称、随装配套类....
微控制器制造商的开发板,以及他们与开发板一起提供的软件项目例程,在工程师着手一个新设计时可以提供很大....
科学技术的进步带来了物流业的巨大变化,从机械化向自动化、智能化发展。我国物流业起步较晚,目前还处于人....
ARM嵌入式Linux系统开发从入门到精通
概述& & & &
& && &&&Danlaw 作为车用电子设备和嵌入式工程服务的全球...
再离开嵌入式开发之前,我参加了两个项目,一个做车联网的一个做智能监测的。但是当时整个团队的实力都较年....
现如今人们不论各个行业都是争先恐后的去学习编程进去 IT 但是 IT 行业到发展前景如何,今天就给大....
FAT精减版(嵌入式应用的版本)--嵌入式FAT文件系统源码免费下载
本文件系统代码兼容FAT16/FAT32两种文件系统...
TI嵌入式产品总览
BootLoader是一段小程序,主要功能是引导操作系统启动。可以把它想象成PC机Linux上的GR....
嵌入式网络技术是近几年随着计算机网络技术的普及和发展而发展起来的一项新兴概念和技术,它通过为现有嵌入....
GPS智能终端是智能交通系统(ITS系统)的重要组成部分,它将卫星定位技术(GPS)、地理信息系统(....
ZLG致远电子推出了一系列“MCU+无线”核心板,本文以NFC核心板为例讲述基于AWorks平台开发....
本文档的主要内容详细介绍的是C程序设计的详细中文资料免费下载内容包括了: 程序设计和C语言,算法--....
该评估模块为Trf7960A/-70A用户提供了使用TF79X0A IC连接到德克萨斯仪器嵌入式微控....
闸门系统是水资源调度中重要的组成部分,国内目前多采用手动和部分电动的操作方式,真正实现闸门的智能控制....
状态监测与故障诊断技术是现代工业技术发展的产物,已发展到了以专家系统、神经网络和模糊分析等理论为基础....
传统的视频监控系统主要以模拟信号监控系统和基于插卡的数字监控系统为主。其中模拟信号监控系统布线工程量....
摘 要: 针对当前高采样率ADC成本高昂、采样精度较低的问题,提出了基于欠采样的信号频率估计方法,通过组合使用低速ADC,...
中国北京,日 - 全球领先的嵌入式解决方案供应商赛普拉斯半导体公司(纳斯达克代码:....
作者:Steve Leibson ,编译:stark
随着消费电子、物联网等领域的不断发展,用户需求也越来越复杂和多样,因此我们在嵌...
现在,我们每天使用的很多设备都利用了神经网络技术:在智能手机中它们为照片搜索功能提供支持,还用于人脸....
无线连接是像智能灯泡、遥控装置、智能建筑传感器和执行器、智能电表、可穿戴设备(含健身设备)、安全报警....
Ti的哪个库可以调用C语言随机数产生函数啊,就是怎么在CCS里产生随机数啊...
根据IEEE(国际电机工程师协会)的定义,嵌入式系统是“控制、监视或者辅助装置、机器和设备运行的装置”(原文为devi...
变压器终端装置TTU、配电终端装置DTU和馈线终端装置TTU等终端装置通过RS232、RS485、C....
随着微电子技术和计算机技术的发展,嵌入式技术得到广阔的发展空间,特别是进入20世纪90年代以来,嵌入....
在现代化生产中, 为了确保机械设备安全可靠地运行, 通常要采用适宜的仪器仪表, 利用故障诊断技术及时....
挑战: 为汽车燃料电池系统开发一个电子控制设备(ECU),显著改善燃料电池系统使其较之于传统的基于内....
借助面向嵌入式系统设计的NI LabVIEW软件,用户无需编写连续多行文本,而是通过拖放式图标开发控....
在设计过程的早期考虑您的发布硬件的设计目标,可以帮助您缩短产品上市时间。您无需重复劳动,可以通过使用....
假设某个机器控制系统用以控制直线台、旋转多轴、控制照明并读取视频数据;在这样一个系统中,则必须以确定....
LSTM隐层神经元结构: LSTM隐层神经元详细结构:
//让程序自己学会是否需要进位,从而学会加....
随着经济的飞速发展,各种各样的监控设备已经随处可见,在不同的领域中发挥着重要的作用。但是诸如保密室、....
嵌入式WiFi技术是当前无线网络应用的一个热点。本文介绍IEEE802.11b的基本技术,给出一种在....
让你知道什么是 C语言 指针,为什么用指针,从此不在害怕指针。
我们平常所说的执行效率就是使用相同的算法在相同输入条件下完成相同计算所产生的系统开销,目前来说一般会....
嵌入式系统(Embedded Systems)是以应用为中心,以计算机技术为基础,软件硬件可剪裁(....
M8LB1 /BB3包含一个I2CSLAVE外设,它包含许多有助于高速传输的功能,但可能会使熟悉传统....
嵌入式技术已在人们生活中得到广泛应用,移动计算更是给人们的生活带来了极大的方便,由移动计算技术推动发....
试想一下,在一个通常性能受限的嵌入式架构中去跑复杂的视觉处理算法,还要平衡功耗、尺寸、成本、开发周期....
在近场通讯 (NFC) 设计中,开发人员向来都面临各种关于优化射频性能、硬件设计和软件方面的挑战。 ....
本指南介绍如何安装、配置和使用用于嵌入式应用程序的 emWin 图形用户界面,还将说明软件的内部结构....
供应链服务
版权所有 (C) 深圳华强聚丰电子科技有限公司
电信与信息服务业务经营许可证:粤B2-

我要回帖

更多关于 c语言整数除小数 的文章

 

随机推荐