利用php unpack读取c struct的二进制数据,struct内存对齐引起的一些问题
c语言代码
#include <stdio.h> struct test{ int a; unsigned char b; int c; }; int main(){ FILE *fp; fp = fopen("t.log", "w+"); struct test t={1234, 'a', 4321}; struct test t1; fwrite(&t, sizeof(struct test), 1, fp); rewind(fp); fread(&t1, sizeof(struct test), 1, fp); printf("%d\n%c\n%d\n", t1.a, t1.b, t1.c); fclose(fp); return 0; }
C的struct 编译器在编译的时候会内存对齐,看到的是12字节,而不是9字节
ls -l //可以看到大小12 -rwxrwxrwx 1 root root 12 4月 12 00:07 t.log od t.log //以八进制查看文件 0000000 002322 000000 000141 000000 010341 000000 0000014
php读取
<?php $fd=fopen("t.log","r"); //知道C的struct 编译器在编译的时候会内存对齐,直接读取12B的大小 $bin = fread($fd, 12); $pack = unpack("Ia/Cb/Ic",$bin); var_dump($pack); fclose($fd);
结果
php t.php array(3) { ["a"]=> int(1234) ["b"]=> int(97) ["c"]=> int(-520093696) } c 的结果-52009369显示不对
经过一顿调试发现,还是没有完全理解 内存对齐
按照内存对齐规则 unsigned char b;会有4个字节的空间,第一个存储数据,其余三个空闲
struct test{ int a; [1-4] unsigned char b; [5-8]//这里是4个而非一个,空闲三个 int c;[9-12] };
<?php //注意这里改成C4 $pack = unpack("Ia/C4b/Ic",$bin); php t.php
array(6) {
["a"]=> int(1234)
["b1"]=> int(97)
["b2"]=> int(0)
["b3"]=> int(0)
["b4"]=> int(0)
["c"]=> int(4321)
}
多出来b2,b3,b4
//这里采用字符串,而非字符 $pack = unpack("Ia/a4b/Ic",$bin); php t.php array(3) { ["a"]=> int(1234) ["b"]=> string(1) "a" ["c"]=>int(4321) } 结果正常了