首页 ? php扩展开发 ? 使用C开发PHP扩展全过程及相关细节(2)-- 变量字符串

使用C开发PHP扩展全过程及相关细节(2)-- 变量字符串

添加评论 次yabo2018.net 注册网

【提示】 非法信息举报请联系本站小编 QQ:5.4069748.5

本文来自网络,原文链接:http://blog.sina.com.cn/s/blog_54ef398901013tub.html

之前一篇介绍了PHP扩展环境搭建及大致项目结构流程介绍
这章将围绕PHP以及C语言变量进行介绍

C语言字符串指针及操作函数
这里主要介绍字符串操作相关,可能大家会很奇怪,为什么我介绍的都是关于变量和字符串的操作知识。事实上我们的网页服务器大部分时间都是在拼接字符串,所以我们用c扩展的时候大部分时间都是在针对内存空间内的字符串进行操作,而php扩展和php交互的时候是通过变量进行传递所以字符串操作和转换是这个里面的基本操作……

以下指针数据类型都是char类型,不同类型的指针移动指针时会移动不同长度。

实际看几个例子
char长度为一字节,16进制为 0xFF??????2进制为1111 1111
int为两个字节?????16进制为 0xFFFF,??2进制为1111 1111 1111 1111
注意:如果在声明类型未指定 unsigned时,那么以上两个类型的 2进制第一位将作为正负值判断而不作为表示数值 1代表负数,0为正数。

注意:上文提到的int并不一定是两个字节,这个长度取决于系统,在32位系统和64位系统中实际表示长度不同。所以,对这类不同系统有变长的变量用其他指针读取的时候务必用sizeof算一下他的长度。

char teststring[50];
声明一个teststring字符串,最大长度50,这个方式在程序执行完毕后会自动释放,这个方式很环保……我目前最喜欢的方式,当然这个方式会浪费一定内存空间……并且不灵活(定长)……不过好在目前这个需求是够用的……

char *ptest;
声明一个字符串指针,注意目前他指向地址未知,我们程序在指定有效空间之前不要对他进行操作,否则肯定会会导致程序崩溃,系统不稳定。

下面两步就是给指针指向一个合法分配的内存空间。

ptest=teststring;
让指针指向teststring的存储空间,这里指针变量实际存储的是这个char串的首个char的内存地址,对与c来说一个字符串在内存中是一个连续的内存空间,在读取使用字符串的时候碰到''时代表这个字符串结束,如果某字符串超过分配空间大小……等着系统挂掉吧……c是不会检测溢出这类事情的……

ptest=malloc(sizeof(char)*50);
此为在运行期间动态分配一块长度为char类型长度*50的空间,这里务必注意在使用完毕后程序结束之前必须释放,否则会导致这块内存在系统重启前不能被其他程序使用,如果调用频繁会导致系统没有可用内存……。

ptest?当前指针地址

*(ptest+1)?相当于teststring[1],即指向第二个字符;

(*ptest)++?相当于teststring[0]++,即指向的第一个字符变量内值+1;

ptest++?相当于teststring[1],这里不同的是以后代码使用ptest时他指向的地址将不是第一个字符,而是第二个,再次提示不同数据类型步进字节个数不同。

关于字符串结尾注意事项
malloc后以及teststring声明后,我们在上面操作中并没有给他赋任何数值,所以他们目前的内容是随机的,务必在对他们进行赋值后再做其他读 取操作,至少要赋值''在首个char内,否则很可能会导致输出50个char内存空间内数据后还会继续输出后面的内存空间内数据直到碰到''。 如果没有进行任何初始化动作直接进行操作的结果会很悲剧。

C一些变量操作函数,这里只是简单罗列一下具体细节自己查看下
strcat(dst,src);????????????????????字符串拼接,将src追加在dst字符串结尾
sprintf(dst,"%ld",idx)??????????????将int转换成显示的char,如123转换成"123"保存到dst内
sscanf("123456 ", "%s", dst);???????将string转换成int,保存到dst内
memset(dst,'',100);???????????????将dst内存区域长度100全部填入
strncpy(dst, src, len);?????????????将src,拷贝到dst,拷贝长度len,这个不会在结尾打要注意

php扩展的一些函数
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str1, &strlen);用于接收函数后参数
注意这里的s代表传入数据为字符串,后面str1为接收字符串变量,strlen为字符串长度,目前已知字符串长度超过4k会被自动截断。其他类型及相关方法,可以参考网上资料……


注意:记得在变量之间来回拷贝追加的时候记得自己判断下追加长度是否超过目前(最大空间长度-1,减1是给结尾用),否则会溢出……哎各种溢出。另外,注意一下这几个函数输入输出的数据类型……

PHP变量在C语言的操作
PHP内的脚本经过Zend引擎“翻译”后,变成OPCODE,Zend根据OPCODE做调用以下c方法完成变量的操作
由于内容很多,这里不一一叙述,只是列出一个网上找到的PHP数组操作与C数组操作对应函数操作对比

PHP语法 ???????????C语法(arr是zval*) ??????????意义
$arr = array(); ????array_init(arr); ???????????????初始化一个新数组
$arr[] = NULL; ?????add_next_index_null(arr); ??????向数字索引的数组增加指定类型的值
$arr[] = 42; ???????add_next_index_long(arr, 42);
$arr[] = true; ?????add_next_index_bool(arr, 1);
$arr[] = 3.14; ?????add_next_index_double(arr, 3.14);
$arr[] = 'foo'; ????add_next_index_string(arr, "foo", 1);
$arr[] = $myvar; ???add_next_index_zval(arr, myvar);
$arr[0] = NULL; ????add_index_null(arr, 0); ????????向数组中指定的数字索引增加指定类型的值
$arr[1] = 42; ??????add_index_long(arr, 1, 42);
$arr[2] = true; ????add_index_bool(arr, 2, 1);
$arr[3] = 3.14; ????add_index_double(arr, 3, 3.14);
$arr[4] = 'foo'; ???add_index_string(arr, 4, "foo", 1);
$arr[5] = $myvar; ?????add_index_zval(arr, 5, myvar);
$arr['abc'] = NULL;????add_assoc_null(arr, "abc"); ????向关联索引的数组增加指定类型的值
$arr['def'] = 711;?????add_assoc_long(arr, "def", 711);
$arr['ghi'] = true; ??