分类 PHP 下的文章

php使用类名实例化类中的坑

以前都是在全局空间(global space)下使用类名变量来实例化类。最近的需求里有一个在命名空间里面实例化一个类,既然是同一个命名空间,理所当然就想到直接用类名就好了,因为在同一命名空间里,用常规的new类名实例化类的时候也是不需要额外指定完整命名空间的。

结果发现,找不到类,由此看来,通过类名变量来实例化类的时候,是在全局变量里面查找类名的。

 

namespace text;
class User{
function say(){
echo "xxxxx";
}
}
//$f="User"; //error
$f="text\\User";
$o = new $f();
$o->say();

后来使用__NAMESPACE__常量来获取类所在的命名空间的时候发现直接在new里面连接字符串会出语法错误,可见php的语法解析在new这里只允许了变量和类名,不允许表达式。

$f="User";
$o = new (__NAMESPACE__ . '\\' .$f)();
$o->say();//error

为了证实这一点,到php的git 找下语法文件。Zend目录下zend_language_parser.y文件就是了。

%token T_NEW "new (T_NEW)"
new_expr:
 	T_NEW class_name_reference ctor_arguments
 	{ $$ = zend_ast_create(ZEND_AST_NEW, $2, $3); }
 	| T_NEW anonymous_class
 	{ $$ = $2; }
class_name_reference:
 	class_name { $$ = $1; }
 	| new_variable { $$ = $1; }
 	;
new_variable:
 	simple_variable
 	{ $$ = zend_ast_create(ZEND_AST_VAR, $1); }
 	| new_variable '[' optional_expr ']'
 	{ $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
 	| new_variable '{' expr '}'
 	{ $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
 	| new_variable T_OBJECT_OPERATOR property_name
 	{ $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); }
 	| class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
 	{ $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
 	| new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable
 	{ $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
 	;

很明显可以看到,new的语法是new 后面加类名/各种变量/匿名类定义。

由此可见,php语法设计有很多地方缺乏一致性,这是因为早期设计比较简单,后面增加大量功能为了兼容性,又修修补补,导致一致性比较差。

C11标准

C11标准是C语言标准的第三版(2011年由ISO/IEC发布),前一个标准版本是C99标准。相比C99,C11有哪些变化呢——

1、 对齐处理

alignof(T)返回T的对齐方式,aligned_alloc()以指定字节和对齐方式分配内存,头文件<stdalign.h>定义了这些内容。

2、 _Noreturn

_Noreturn是个函数修饰符,位置在函数返回类型的前面,声明函数无返回值,有点类似于gcc的attribute((noreturn)),后者在声明语句尾部。

3、 _Generic

_Generic支持轻量级范型编程,可以把一组具有不同类型而却有相同功能的函数抽象为一个接口。

4、 _Static_assert()

_Static_assert(),静态断言,在编译时刻进行,断言表达式必须是在编译时期可以计算的表达式,而普通的assert()在运行时刻断言。

5、安全版本的几个函数

gets_s()取代了gets(),原因是后者这个I/O函数的实际缓冲区大小不确定,以至于发生常见的缓冲区溢出攻击,类似的函数还有其它的。

6、 fopen()新模式

fopen()增加了新的创建、打开模式“x”,在文件锁中比较常用。

7、 匿名结构体、联合体。

8、 多线程

头文件<threads.h>定义了创建和管理线程的函数,新的存储类修饰符_Thread_local限定了变量不能在多线程之间共享。

9、 _Atomic类型修饰符和头文件<stdatomic.h>。

10、改进的Unicode支持和头文件<uchar.h>。

11、quick_exit()

又一种终止程序的方式,当exit()失败时用以终止程序。

12、复数宏,浮点数宏。

13、time.h新增timespec结构体,时间单位为纳秒,原来的timeval结构体时间单位为毫秒。

Source: xundaoinfo