![bb88f95ff8f9831bf43848dde90984a5.png](https://i-blog.csdnimg.cn/blog_migrate/8a64329e68d2b8133b9edb1fcc05fb9b.jpeg)
在学习PHP的字符串时,我们知道存储在zend_string中,来看一下
struct _zend_string {zend_refcounted_h gc;zend_ulong h; /* hash value */size_t len;char val[1];};
这里 char val[1] 只占一个字节内存,我们可能会感到奇怪,长度为1的数组如何存的下大于1长度的字符串呢,其实这里利用了C的柔性数组。
柔性数组可以认为是边长数组,只能出现在结构体的最后一个成员位置,它可以自动扩容。
上面是柔性数组的一种形式,柔性数组还有一种形式 char val[], 这是由于遵循的标准不一样。
来看例子
int main(){ /** * 柔性数组可以理解为非定长数组,实际的长度是动态的 * 1、必须要声明在结构体的结尾 * 2、不占用内存 * 3、使用内存缓冲区 * 4、自动扩容 */ struct User { int age; int stuID; char address[]; // 结构体结尾 }; // 8 两个int 4 + 4 // char address[] 不占内存 printf("size of user %lu ", sizeof(struct User)); struct User jack; // address赋值 jack.address[0] = 'b'; jack.address[1] = 'e'; jack.address[2] = 'i'; jack.address[3] = 'j'; jack.address[4] = 'i'; jack.address[5] = 'n'; jack.address[6] = 'g'; jack.stuID = 1; // 8 说明 address并没有占用内存 printf("size of jack %lu ", sizeof(jack)); // beijing printf("address is %s ", jack.address); printf("*************下面使用指针来************ "); struct Stu { int age; int stdID; char *address; }; // 16 int + int + char的指针 4+4+8 // 明显指针是占用内存的 printf("size of std %lu ", sizeof(struct Stu)); char myAddress[7]; myAddress[0] = 't'; myAddress[1] = 'i'; myAddress[2] = 'a'; myAddress[3] = 'n'; myAddress[4] = 'j'; myAddress[5] = 'i'; myAddress[6] = 'n'; struct Stu rose; rose.address = myAddress; rose.stdID = 2; printf("size of rose %lu ", sizeof(rose)); printf("address is %p ", rose.address); printf("address[0] is %c ", *(rose.address)); printf("address[1] is %c ", *(rose.address+1)); printf("*************柔性数组的第二种方式************ "); struct zend_string { int refcount; int len; char val[1]; }; // 12 字节 int +int + char内存对齐 4*3 printf("size of zend_string %lu ", sizeof(struct zend_string)); struct zend_string str1; str1.len = 5; str1.val[0] = 'h'; str1.val[1] = 'e'; str1.val[2] = 'l'; str1.val[3] = 'l'; str1.val[4] = 'o'; // 12 val赋值之后仍然内存空间没有变化 printf("size of zend_string %lu ", sizeof(str1)); // hello printf("size of zend_string.val %s ", str1.val); /** * struct _zend_string { * zend_refcounted_h gc; * zend_ulong h; * size_t len; * char val[1]; * }; * * * * * */ /** * val[] 与 val[1] 两种实现方式不太一样,因为标准不一样 * c99 标准中允许 char val[] 这种定义作为柔性(不定长)数组出现,他不占用内存空间 * c99之前只支持 char val[1]这种格式,占用1个字节 */ return 0;}
总结:
柔性数组可以理解为非定长数组,实际的长度是动态的
- 必须要声明在结构体的结尾
- 不占用内存
- 使用内存缓冲区
- 自动扩容