zoukankan      html  css  js  c++  java
  • 大神洗礼第三讲——接上一讲

    Author:bakari                 Date:2012.10.26

    这一讲的主要内容和上一讲相同,是上一讲的深入分析。内存对齐涉及内存实现的细节,复杂声明是对指针的深入理解,这些内容平时用到很少,学习之益于开拓思维,达到宏观调控自己的知识结构。

    1、对于内存对齐上一讲没有提到计算的方法,其实上一讲的内容足以解决如何计算的问题,但有个规律或许会更容易计算。下面是概况出来的规律:

    < 1 >、编译器默认对齐的字节:8字节,对齐字节数只能选2^n(一般不超过16字节)
               在程序中用#pragma back( X ) ……. #pragma pop()来转换。

    < 2 >、单个成员变量的自身对齐位:min(默认对齐位,本身所占字节数)

    < 3 >、结构体的有效对齐位:该结构体(或union或class)的成员变量中,
               min(最大所占位数,默认对齐位)
               其中< 2 >可以不考虑,< 3 >是考虑的关键

    < 4 >、除以上3点外,还要考虑一个关键特性:圆整。          

               何为圆整?每个变量所占字节数之和与 < 3 >中的有效对齐位求模,如若为0,则不作改变,否则,系统自动以 CC 作为填充,以保证对齐。

    E.g:具体看下面的几个例子:

    1 struct Test {
    2       char   szA[5];
    3       double dB;
    4       int    iC;
    5       char   cD;
    6 };

    编译器的默认对齐位是:8 即#pragma back (8),结构体最大的成员变量是dB,占8个字节,所以结构体的有效对齐位是 8.
    通过上面三条规则,可以得出:sizeof(Test)= 5 + 3cc + 8 + 4 + 1 + 3cc = 24;
    内存布局:

    < 2 >、将double dB 改为int iB;

    1     struct Test {
    2       char   szA[5];
    3       int    iB;
    4       int    iC;
    5       char   cD;
    6 };

    同理,sizeof(Test) = 5 + 3cc + 4 + 4 + 1 + 3 cc = 20;
    内存布局:

    < 3 >较为复杂,道理一样,分开看

     1 struct AX {                               
     2     void *pC;
     3     char cA;
     4     char szBuf[3];
     5     int  iB;
     6     void *p;
     7 };
     8 
     9 union BX {
    10     double dA;
    11     int    iB
    12 };
    13 
    14 struct xTest {
    15     int    iA;
    16     int    iB;
    17     char   cC;
    18     void   *pD;
    19     char   *pVoid;
    20     AX     objAX;
    21     BX     objBX;
    22     char   cE;
    23     double dF;
    24 };

    直接看内存布局:(sizeof(xTest) = 64)

    2、复杂声明我就不多讲了,想了解的朋友可以去看我的另一篇文章:http://www.cnblogs.com/bakari/archive/2012/08/28/2659889.html

    这里我们来点刺激的,将复杂声明的语句用机器打印出来,换句话说不是你来说,而是交给机器来显示:(关于这一点The C programming language一书有讲)

    我们直接看代码:(只显示三个主要的函数)

     1 int gettoken(void)
     2 {
     3     char c;
     4     char *p = token;
     5 
     6     while ((c = getch()) == ' ' || c == '\t');
     7     if (c == '(') {
     8         if ((c = getch()) == ')') {
     9             strcpy(token, "()");
    10             return tokentype = PARENS;
    11         }
    12         else {
    13             ungetch(c);
    14             return tokentype = '(';
    15         }
    16     }
    17     else if (c == '[') {
    18         for (*p ++ = c; (*p ++ = getch()) != ']'; );
    19         *p = '\0';
    20         return tokentype = BRACKETS;
    21     }
    22     else if (isalpha(c)) {
    23         for (*p ++ =  c; isalnum(c = getch()); )
    24             *p ++ = c;
    25         *p = '\0';
    26         ungetch(c);
    27         return tokentype = NAME;
    28     }
    29     else
    30         return tokentype = c;
    31 }
    32 
    33 void dcl (void)
    34 {
    35     int ns;
    36     for( ns = 0; gettoken() == '*'; )
    37         ns ++;
    38     dirdcl();
    39     while (ns -- > 0)
    40         strcat(out, " pointer to");
    41 }
    42 
    43 void dirdcl(void)
    44 {
    45     int type;
    46 
    47     //void parmdcl(void);
    48     if (tokentype == '(') {
    49         dcl();
    50         if (tokentype != ')')
    51             errmsg("ERROR!:missing ) \n");
    52             //printf("ERROR!:missing ) \n");
    53     }
    54     else if (tokentype == NAME) {
    55         //if (name[0] == '\0')
    56             strcpy(name, token);
    57     }
    58     else
    59         //errmsg("ERROR: expected name or (dcl) \n");
    60         prevtoken = YES;
    61     while ((type = gettoken()) == PARENS || type  == BRACKETS || type == '(') {
    62         if (type == PARENS)
    63             strcat (out, " function returning");
    64         else if (type == '(') {
    65             strcat(out , "function expecting");
    66             parmdcl();
    67             strcat(out, " and returning");
    68         }
    69         else {
    70             strcat(out, " array");
    71             strcat(out, token);
    72             strcat(out, " of");
    73         }
    74     }
    75 }

    更多干货请移步我的公众号「aCloudDeveloper」,专注技术干货分享,期待与你相遇。

    stay hungry stay foolish ----jobs 希望多多烧香!
  • 相关阅读:
    用SQL完成條件式查詢[收藏From 黃偉榮]
    asp.net代码中尖括号和百分号的含义
    Python读取文本,输出指定中文(字符串)
    nodejs Express 4.x req.body req.query req.params 三种获取参数的方法
    关于ImageMagick出现无效参数(invalid parameter)的解决方法
    JavaScript之数组循环 forEach 循环输出数组元素
    nodejs将PDF文件转换成txt文本,并利用python处理转换后的文本文件
    ImageMagick之PDF转换成图片(image)
    POJ 2635 The Embarrassed Cryptographer(整数刷新,千进制取模)
    js 获取目标网页源码
  • 原文地址:https://www.cnblogs.com/bakari/p/2741860.html
Copyright © 2011-2022 走看看