上海龙凤419

C说话

C说话的底层操纵

时辰:2024-08-23 00:08:45 C说话 我要投稿
  • 相干保举

C说话的底层操纵

  C说话的内存模子根基上对应了此刻von Neumann(冯·诺伊曼)计较机的现实存储模子,很好的到达了对机械的映照,这是C/C++合适做底层开辟的首要缘由,别的,C说话合适做底层开辟另有别的一个缘由,那便是C说话对底层操纵做了良多的的撑持,供给了良多比拟底层的功效。上面就来和小编一路看看C说话的底层操纵吧。

  上面连系题目别离停止论述。

  题目:移位操纵

  在利用移位操纵符时,有两个题目必须要清晰:

  (1)、在右移操纵中,凌空位是填 0 仍是标记位;

  (2)、甚么数能够作移位的位数。

  谜底与阐发

  ">>"和"<<"是指将变量中的每位向右或向左挪动, 其凡是情势为:

  右移: 变量名>>移位的位数

  左移: 变量名<<移位的位数

  颠末移位后, 一端的位被"挤掉",而另外一端空出的位以0 弥补,在C说话中的移位不是轮回挪动的。

  (1) 第一个题目的谜底很简略,但要按照差别的环境而定。若是被移位的是无标记数,则填 0 。若是是有标记数,那末能够填 0 或标记位。若是你想处理右移操纵中凌空位的添补题目,就把变量申明为无标记型,如许凌空位会被置 0。

  (2) 第二个题目的谜底也很简略:若是挪动 n 位,那末移位的位数要不小于 0 ,并且必然要小于 n 。如许就不会在一次操纵中把一切数据都移走。

  比方,若是整型数据占 32 位,n 是一整型数据,则 n << 31 和 n << 0 都正当,而 n << 32 和 n << -1 都不正当。

  注重即便凌空位填标记位,有标记整数的右移也不相称与除以 。为了证实这一点,咱们能够想一下 -1 >> 1 不能够为 0 。

  题目:位段布局

struct RPR_ATD_TLV_HEADER
       {
       ULONG res1:6;
       ULONG type:10;
       ULONG res1:6;
       ULONG length:10; 
       };

  位段布局是一种出格的布局, 在需按位拜候一个字节或字的多个位时, 位布局比按位运算符加倍便利。

  位布局界说的普通情势为:

struct位布局名{ 
        数据范例 变量名: 整型常数; 
        数据范例 变量名: 整型常数; 
       } 位布局变量;

  此中: 整型常数必须长短负的整数, 规模是0~15, 表现二进制位的个数, 即表现有几多位。

  变量名是挑选项, 能够不定名, 如许划定是为了摆列须要。

  比方: 上面界说了一个位布局。

struct{ 
        unsigned incon: 8; /*incon占用低字节的0~7共8位*/ 
        unsigned txcolor: 4;/*txcolor占用高字节的0~3位共4位*/ 
        unsigned bgcolor: 3;/*bgcolor占用高字节的4~6位共3位*/ 
        unsigned blink: 1; /*blink占用高字节的第7位*/ 
       }ch;

  位布局成员的拜候与布局成员的拜候不异。

  比方: 拜候上例位布局中的bgcolor成员可写成:

ch.bgcolor

  位布局成员能够与别的布局成员一路利用。 按位拜候与设置,便利&节流

  比方:

struct info{ 
        char name[8]; 
        int age; 
        struct addr address; 
        float pay; 
        unsigned state: 1; 
        unsigned pay: 1; 
       }workers;'

  上例的布局界说了对一个工从的信息。此中有两个位布局成员, 每一个位布局成员只要一名, 是以只占一个字节但保管了两个信息, 该字节中第一名表现工人的状况, 第二位表现人为是不是已发放。因而可知利用位布局能够节流存贮空间。

  注重不要跨越值限定

  题目:字节对齐

  我在利用VC编程的进程中,有一次挪用DLL中界说的布局时,觉察布局都乱掉了,完整不能读取准确的值,厥后发明这是由于DLL和挪用法式利用的字节对齐选项差别,那末我想问一下,字节对齐事实是怎样一回事?

  谜底与阐发:

  对字节对齐:

  1、 当差别的布局利用差别的字节对齐界说时,能够致使它们之间交互变得很坚苦。

  2、 在跨CPU停止通信时,能够利用字节对齐来保障独一性,诸如通信和谈、写驱动法式时辰寄放器的布局等。

  三种对齐体例:

  1、 天然对齐体例(Natural Alignment):与该数据范例的巨细相称。

  2、 指定对齐体例 :

#pragma pack(8) //指定Align为 8;
       #pragma pack() //规复到本来值

  3、 现实对齐体例:

Actual Align = min ( Order Align, Natual Align )

  对庞杂数据范例(比方布局等):现实对齐体例是其成员最大的现实对齐体例:

Actual Align = max( Actual align1,2,3,…)

  编译器的添补纪律:

  1、 成员为成员Actual Align的整数倍,在前面加Padding。

  成员Actual Align = min( 布局Actual Align,设定对齐体例)

  2、 布局为布局Actual Align的整数倍,在前面加Padding.

  例子阐发:

#pragma pack(8) //指定Align为 8
       struct STest1
       {
       char ch1; 
       long lo1;
       char ch2;
       } test1;
       #pragma pack()

  此刻

Align of STest1 = 4 , sizeof STest1 = 12 ( 4 * 3 )

  test1在内存中的摆列以下( FF 为 padding ):

00 -- -- -- 04 -- -- -- 08 -- -- -- 12 -- -- --
       01 FF FF FF 01 01 01 01 01 FF FF FF 
       ch1 -- lo1 -- ch2
       #pragma pack(2) //指定Align为 2
       struct STest2
       {
       char ch3;
       STest1 test;
       } test2;
       #pragma pack()

  此刻 Align of STest1 = 2, Align of STest2 = 2 , sizeof STest2 = 14 ( 7 * 2 )

  test2在内存中的摆列以下:

00 -- -- -- 04 -- -- -- 08 -- -- -- 12 -- -- --
       02 FF 01 FF FF FF 01 01 01 01 01 FF FF FF 
       ch3 ch1 -- lo1 -- ch2

  注重事变:

  1、 如许一来,编译器没法为特定平台做优化,若是效力很是主要,就尽可能不要利用#pragma pack,若是必须利用,也最好仅在须要的处所停止设置。

  2、 须要加pack的处所必然要在界说布局的头文件中加,不要依靠号令行选项,由于若是良多人利用该头文件,并不是每一小我都晓得应当pack。这出格表此刻为别人开辟库文件时,若是一个库函数利用了struct作为其参数,当挪用者与库文件开辟者利用差别的pack时,就会形成毛病,并且该类毛病很不好查。

  3、 在VC及BC供给的头文件中,除能恰好对齐在四字节上的布局外,都加了pack,不然咱们编的Windows法式哪个也不会一般运转。

  4、 在 #pragma pack(n) 后必然不要include其余头文件,若包罗的头文件中转变了align值,将发生非预期成果。

  5、 不要多人同时界说一个数据布局。如许能够保障分歧的pack值。

  题目:按位运算符

  C说话和别的高等说话差别的是它完整撑持按位运算符。这与汇编说话的位操纵有些类似。 C中按位运算符列出以下:

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  操纵符 感化

  ────────────────────────────

  & 位逻辑与

  | 位逻辑或

  ^ 位逻辑异或

  - 位逻辑反

  >> 右移

  << 左移

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  注重:

  1、 按位运算是对字节或字中的现实位停止检测、设置或移位, 它只合用于字符型和整数型变量和它们的变体, 对别的数据范例不合用。

  2、 干系运算和逻辑运算抒发式的成果只能是1或0。 而按位运算的成果能够取0或1之外的值。 要注重区分按位运算符和逻辑运算符的差别, 比方, 若x=7, 则x&&8 的值为真(两个非零值相与仍为非零), 而x&8的值为0。

  3、 | 与 ||,&与&&,~与! 的干系

  &、| 和 ~ 操纵符把它们的操纵数看成一个为序列,按位零丁停止操纵。比方:10 & 12 = 8,这是由于"&"操纵符把 10 和 12 看成二进制描写 1010 和 1100 ,以是只要当两个操纵数的不异位同时为 1 时,发生的成果中响应位才为 1 。同理,10 | 12 = 14 ( 1110 ),经由过程补码运算,~10 = -11 ( 11...110101 )。<以几多为一个位序列> &&、|| 和!操纵符把它们的操纵数看成"真"或"假",并且用 0 代表"假",任何非 0 值被以为是"真"。它们前往 1 代表"真",0 代表"假",对"&&"和"||"操纵符,若是左边的操纵数的值就能够决议抒发式的值,它们底子就不去计较右边的操纵数。以是,!10 是 0 ,由于 10 非 0 ;10 && 12 是 1 ,由于 10 和 12 均非 0 ;10 || 12也是 1 ,由于 10 非 0 。并且,在最初一个抒发式中,12 底子就没被计较,在抒发式 10 || f( ) 中也是如斯。

【C说话的底层操纵】相干文章:

C说话位操纵是甚么?12-04

2017计较机二级《C说话》操纵试题及谜底03-24

C说话考点精选03-18

C说话试题03-28

C说话的利用12-12

C说话的布局12-12

计较机二级《C说话》操纵试题与谜底201603-11

甚么是C说话03-19

C说话试题(精选)12-05