我正在使用 Windows 10家庭单一语言版,它是计算机上的 64位操作系统。
我已经安装了最新版本的 XAMPP ,该版本已在计算机上安装了 PHP 7.2.7 。
我要根据PHP Manual中的摘录问这个问题:
PHP中的字符串被实现为字节数组和整数 指示缓冲区的长度。它没有有关如何 这些字节会转换为字符,从而将任务留给 程序员。字符串的值没有限制 由...组成的;特别是,值为0的字节(“ NUL字节”)为 允许在字符串中的任何位置(但是,在此表示一些功能 手册不要“二进制安全”,可能会将字符串移交给库 会忽略NUL字节后的数据。)
我非常了解PHP中的二进制安全函数和非二进制安全函数之间的区别。我心中一直在怀疑。请以一对一的方式回答这些问题,并提供适当的说明和适当的示例。
答案 0 :(得分:9)
就像arkascha所解释的那样,“二进制安全”和“非二进制安全”的问题与该语言无关。
使用一个空字节(0x00)来指示字符串的结尾更简单(这可能是C随其而来的原因), 但不利的一面是,字符串中的任何地方都不能有一个空字节 如果您必须能够处理各种数据,这是一个很大的限制。 如Pete所示,将长度存储为字符串的元数据部分更为复杂,但是它允许您处理任何类型的数据。
关于“二进制安全”或“非二进制安全”的功能, 只需在使用该功能之前之前阅读PHP手册。 我就是做这个的。 无需构造列表,因为PHP手册已经说明了您需要了解的有关函数的知识,包括它们是否二进制安全。
我相信您的大部分帖子是由于您引用的PHP手册的解释有误,尤其是这部分:
但是,本手册中所说的某些不是“二进制安全”的功能可能会将字符串传递给忽略NUL字节后的数据的库。
让我尝试通过添加一些自己的词来使其更清晰:
但是,一些功能在本手册中表示不是“二进制安全的”,是可以将字符串移交给忽略NUL字节后的数据的库的功能。
因此,它实际上并没有说“非二进制安全函数将字符串移交给库”,这是一种误解。 意思是“本函数中所说的函数可能会将字符串传递给忽略NUL字节后的数据的库,因此不是二进制安全的”。
“移交给库”只是说“从其他库调用函数”的另一种方式。 “忽略NUL字节后的数据”是一种不安全的二进制行为。
另一种放置方式是:
本手册中的某些功能被称为不是“二进制安全的” ,因为它们可能会调用其他非“二进制安全的”功能(忽略NUL字节后的数据的功能)。
我希望这可以为您清除它。
答案 1 :(得分:5)
传统上,有两种表示字符串的方法:通过使用特殊字符来表示字符串的结尾,或者将其长度与字符串数据一起存储。 C使用前者;字符串是一个以结尾为空字符的字符数组。但是,这样做的局限性在于,C语言中的字符串只能在结尾处使用空字符。
为克服此限制,PHP引擎使用此结构表示字符串:
struct _zend_string {
zend_refcounted_h gc; /* refcount struct */
zend_ulong h; /* hash value */
size_t len; /* length of string */
char val[1]; /* array of chars (using struct "hack") */
};
如您所见,PHP开发人员选择将字符串的长度及其数据一起存储。
现在,如果混合使用“二进制安全”和“非二进制安全”功能会发生什么?
请考虑以下在编写PHP扩展时可能使用的C代码:
zend_string *a = zend_string_init("a\0b", /* string length */ 3, 0);
zend_string *b = zend_string_init("a\0c", /* string length */ 3, 0);
if (strcmp(a->val, b->val) == 0) {
php_printf("Strings are equal!");
}
您认为会发生什么?此代码输出“字符串相等!”他们显然不平等。由于strcmp
并未考虑字符串的长度,因此它是一个非二进制安全函数。
C的大多数标准库字符串函数都可归类为“非二进制安全”,因为它依赖于空终止符。
在扩展代码中处理zend_string
时,应使用Zend字符串函数(zend_string_*
)而不是C的字符串库。
要修复先前的代码,请执行以下操作:
if (zend_string_equals(a, b)) {
php_printf("Equal!");
} else {
php_printf("Not equal");
}
现在可以正确打印“不相等”。
答案 2 :(得分:3)
一个功能是否以“二进制安全”的方式处理运行时数据的问题与实现系统所用的语言无关。这是一个如何处理数据的问题。 PHP是一种高级语言,这意味着它具有字符串类型的高级实现。这并不取决于C所依赖的终止空字符,而是字符串类型维护有关所存储字符串的元数据,这允许更加灵活和健壮的实现。但是,这与是否“二进制安全”无关。
您的其他观点并不能真正以清晰的方式得到回答。 php使用的库本身取决于您的设置,即动态环境。潜在的库如何处理移交给他们的数据又与php函数是否可以被认为是“二进制安全的”无关-库不了解php,它仅根据库的方式移交数据并进行处理已实施。