struct packing

数据对齐

通常, 处理器提供的访问字 (4 Byte) 指令都只能访问对齐的地址. 因此, int 变量的地址一定是 4 字节对齐的. 违反对齐要求, 在如 Sparc 上面是异常, 在如 x86 上面会导致异常还是访问速度变慢我也记不清了.

在 struct 中一样, 如

struct mystruct {
    char a;
    short b;
    char c;
    int d;
};

实际的内存布局是

  0   1   2   3   4   5   6   7   8   9  10  11
+---+---+---+---+---+---+---+---+---+---+---+---+
| a | . |   b   | c | . | . | . |       d       |
+---+---+---+---+---+---+---+---+---+---+---+---+

gcc 中控制布局对齐的方法

可以使用 __attribyte__((...)), 如下程序

struct nopack {
    char a;
    short b;
    char c;
    int d;
};

struct pack {
    char a;
    short b;
    char c;
    int d;
} __attribute__((packed));
// packed works on all members

struct packalign {
    char a;
    short b;
    char c;
    int d;
} __attribute__((aligned(8)));
// aligned works on whole struct instead of members

struct nopack a = {
    .a = 0xAA,
    .b = 0xBBBB,
    .c = 0xCC,
    .d = 0xDDDDDDDD
};

struct pack b = {
    .a = 0xAA,
    .b = 0xBBBB,
    .c = 0xCC,
    .d = 0xDDDDDDDD
};

struct packalign c = {
    .a = 0xAA,
    .b = 0xBBBB,
    .c = 0xCC,
    .d = 0xDDDDDDDD
};

int main()
{
    printf("%d %d %d\n", sizeof(a), sizeof(b), sizeof(c));
}

使用 gcc 编译运行

sizeof(a) sizeof(b) sizeof(c)
12 8 16

使用 objdump 得到如下结果

Contents of section .data:
 601030 00000000 00000000 00000000 00000000  ................
 601040 aa00bbbb cc000000 dddddddd 00000000  ................
 601050 aabbbbcc dddddddd 00000000 00000000  ................
 601060 aa00bbbb cc000000 dddddddd 00000000  ................

使用 nm 得到

0000000000601040 D a
0000000000601050 D b
0000000000601060 D c

检查 gcc 默认的 include 路径

$ gcc -xc -E -v /dev/null

之后输出中包含

#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/5/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include

git 引入其他项目

stackoverflow

使用 read-tree. 假设希望引入在 REMOTE_URL 的项目到目录 REMOTE_PATH 下.

$ git remote add REMOTE_NAME REMOTE_URL
$ git fetch REMOTE_NAME
$ git merge -s ours --no-commit REMOTE_NAME/master
$ git read-tree --prefix=REMOTE_PATH/ -u REMOTE_NAME/master
$ git commit -m "COMMIT MESSAGE"

C 语言博大精深

https://stackoverflow.com/questions/3430315/what-is-the-purpose-of-static-keyword-in-array-parameter-of-function-like-char https://stackoverflow.com/questions/3693429/c-parameter-array-declarators

我不理解为什么今日大家还在用 C 这种难以分析的语言… 虽然我比较喜欢 C, 但是越深入越发现 C 的混乱, 尤其是 declarator 部分和 lvalue 部分.

如下函数有一个神奇的类型 const int* const* const

int main() {
  int v;
  int* y = &v;
  const int* const* const t = (const int* const*)&y;
  t = &y;
  *t = &v;
  **t = 5;
}

编译之后

10:10:51 hob ~/Programs/test % gcc test.c
test.c: In function ‘main’:
test.c:5:5: error: assignment of read-only variable ‘t’
   t = &y;
     ^
test.c:6:6: error: assignment of read-only location ‘*t’
   *t = &v;
      ^
test.c:7:7: error: assignment of read-only location ‘**t’
   **t = 5;
       ^

手动安装 Tex package

假设我们要安装 trfrac. 如果我们编译一个使用 trfrac 的 tex, 但是没有安装的话, latex 会自动提示没有找到 trfrac.sty.

  1. 先去网上找到 trfrac.sty 文件.

  2. 然后直接把 sty 放到全局的 package 目录中. ubuntu 下面这通常是 /usr/share/texmf/tex/latex. (TODO: 找个方法来确定) 把 trfrac.sty 移动到 /usr/share/texmf/tex/latex/trfrac/trfrac.sty.

  3. 运行 sudo texhash.

现在再编译使用 trfrac 的 tex, 就不会报错啦.


服务器配置