2.6 类型转换

现在我们已经可以从符号表中获取用户在PHP语言里定义的变量了,是该做点其它事的时候了,举个例子,比如给它来个类型转换:-)。想想C语言中的类型转换细则,你的头是不是已经大了?但是变量的类型转换就是如此重要,如果没有,那我们的代码就会是下面这样了:

  1. void display_zval(zval *value)
  2. {
  3. switch (Z_TYPE_P(value)) {
  4. case IS_NULL:
  5. /* 如果是NULL,则不输出任何东西 */
  6. break;
  7. case IS_BOOL:
  8. /* 如果是bool类型,并且true,则输出1,否则什么也不干 */
  9. if (Z_BVAL_P(value)) {
  10. php_printf("1");
  11. }
  12. break;
  13. case IS_LONG:
  14. /* 如果是long整型,则输出数字形式 */
  15. php_printf("%ld", Z_LVAL_P(value));
  16. break;
  17. case IS_DOUBLE:
  18. /* 如果是double型,则输出浮点数 */
  19. php_printf("%f", Z_DVAL_P(value));
  20. break;
  21. case IS_STRING:
  22. /* 如果是string型,则二进制安全的输出这个字符串 */
  23. PHPWRITE(Z_STRVAL_P(value), Z_STRLEN_P(value));
  24. break;
  25. case IS_RESOURCE:
  26. /* 如果是资源,则输出Resource #10 格式的东东 */
  27. php_printf("Resource #%ld", Z_RESVAL_P(value));
  28. break;
  29. case IS_ARRAY:
  30. /* 如果是Array,则输出Array5个字母! */
  31. php_printf("Array");
  32. break;
  33. case IS_OBJECT:
  34. php_printf("Object");
  35. break;
  36. default:
  37. /* Should never happen in practice,
  38. * but it's dangerous to make assumptions
  39. */
  40. php_printf("Unknown");
  41. break;
  42. }
  43. }

看完上面的代码,你是不是有点似曾相识的感觉?o(∩∩)o…哈哈,和直接<?php echo $foo;?>这个简单到极点的php语句来比,上面的实现算是天书了。当然,真正的环境并没有这么囧,内核中提供了好多函数专门来帮我们实现类型转换的功能,你需要的只是调用一个函数而已。这一类函数有一个统一的形式:convertto*()

  1. //将任意类型的zval转换成字符串
  2. void change_zval_to_string(zval *value)
  3. {
  4. convert_to_string(value);
  5. }
  6. //其它基本的类型转换函数
  7. ZEND_API void convert_to_long(zval *op);
  8. ZEND_API void convert_to_double(zval *op);
  9. ZEND_API void convert_to_null(zval *op);
  10. ZEND_API void convert_to_boolean(zval *op);
  11. ZEND_API void convert_to_array(zval *op);
  12. ZEND_API void convert_to_object(zval *op);
  13. ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC);
  14. #define convert_to_string(op) if ((op)->type != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); }

这里面有两个比较特殊,一个就是convert_to_string其实是一个宏函数,调用的另外一个函数;第二个便是没有convert_to_resource()的转换函数,因为资源的值在用户层面上,根本就没有意义,内核不会对它的值(不是指那个数字)进行转换。

好了,我们用php的echo的时候会先把变量转换成字符串,但是我们看见convertto_string的参数是zval*的,你是不是开始担心在进行数据转换时破坏了原来数据的值?而我们<?php $a=intval($b);并不会破坏$b的值。把原来的值破坏掉的做法绝对不是一个好主意,内核中在echo一个变量的时候也不是这样做的。在下一章,我们将知道怎样便可以在不损坏原变量值的情况下,进行convert_to类操作。