使用内存引用比较 PHP 数组

发布于 2024-09-30 12:56:03 字数 41 浏览 7 评论 0原文

是否可以查看两个数组变量是否指向同一内存位置? (它们是同一个数组)

Is it possible to see if two array variables point to the same memory location? (they are the same array)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

九局 2024-10-07 12:56:03

事实上,这是可以做到的。通过 php 扩展。

文件:config.m4

PHP_ARG_ENABLE(test, whether to enable test Extension support, [ --enable-test   Enable test ext support])

if test "$PHP_TEST" = "yes"; then
  AC_DEFINE(HAVE_TEST, 1, [Enable TEST Extension])
  PHP_NEW_EXTENSION(test, test.c, $ext_shared)
fi

文件:php_test.h

#ifndef PHP_TEST_H
#define PHP_TEST_H 1

#define PHP_TEST_EXT_VERSION "1.0"
#define PHP_TEST_EXT_EXTNAME "test"

PHP_FUNCTION(getaddress4);
PHP_FUNCTION(getaddress);

extern zend_module_entry test_module_entry;
#define phpext_test_ptr &test_module_entry

#endif

文件:test.c

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_test.h"

ZEND_BEGIN_ARG_INFO_EX(func_args, 1, 0, 0)
ZEND_END_ARG_INFO()

static function_entry test_functions[] = {
    PHP_FE(getaddress4, func_args)
    PHP_FE(getaddress, func_args)
    {NULL, NULL, NULL}
};

zend_module_entry test_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    PHP_TEST_EXT_EXTNAME,
    test_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
#if ZEND_MODULE_API_NO >= 20010901
    PHP_TEST_EXT_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_TEST
ZEND_GET_MODULE(test)
#endif

PHP_FUNCTION(getaddress4)
{
    zval *var1;
    zval *var2;
    zval *var3;
    zval *var4;
    char r[500];
    if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aaaa", &var1, &var2, &var3, &var4) == FAILURE ) {
      RETURN_NULL();
    }
    sprintf(r, "\n%p - %p - %p - %p\n%p - %p - %p - %p", var1, var2, var3, var4, Z_ARRVAL_P(var1), Z_ARRVAL_P(var2), Z_ARRVAL_P(var3), Z_ARRVAL_P(var4) );
    RETURN_STRING(r, 1);
}

PHP_FUNCTION(getaddress)
{
    zval *var;
    char r[100];
    if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &var) == FAILURE ) {
      RETURN_NULL();
    }
    sprintf(r, "%p", Z_ARRVAL_P(var));
    RETURN_STRING(r, 1);
}

然后你所要做的就是 phpize 它,配置它,然后制作它。将“extension=/path/to/so/file/modules/test.so”添加到 php.ini 文件中。最后,重新启动 Web 服务器,以防万一。

<?php
  $x = array("123"=>"123");
  $w = $x;
  $y = $x;
  $z = &$x;
  var_dump(getaddress4($w,$x,$y,$z));
  var_dump(getaddress($w));
  var_dump(getaddress($x));
  var_dump(getaddress($y));
  var_dump(getaddress($z));
?>

返回(至少对我来说,你的内存地址可能会不同)

string '
0x9efeb0 - 0x9effe0 - 0x9ef8c0 - 0x9efeb0
0x9efee0 - 0x9f0010 - 0x9ed790 - 0x9efee0' (length=84)

string '0x9efee0' (length=8)

string '0x9f0010' (length=8)

string '0x9ed790' (length=8)

string '0x9efee0' (length=8)

感谢Artefacto指出了这一点,但我的原始代码是按值传递数组,因此重新创建了包括引用数组在内的数组,并给你带来了糟糕的记忆价值观。此后我更改了代码以强制所有参数通过引用传递。这将允许引用、数组和对象不受 php 引擎干扰地传递。 $w/$z 是同一件事,但 $w/$x/$y 不是。旧代码实际上显示了引用损坏以及当传递所有变量与多次调用同一函数时内存地址会更改或匹配的事实。这是因为 PHP 在执行多个调用时会重用相同的内存。比较原始函数的结果是没有用的。新代码应该可以解决这个问题。

仅供参考 - 我正在使用 php 5.3.2。

Actually, this can be done. Through a php extension.

File: config.m4

PHP_ARG_ENABLE(test, whether to enable test Extension support, [ --enable-test   Enable test ext support])

if test "$PHP_TEST" = "yes"; then
  AC_DEFINE(HAVE_TEST, 1, [Enable TEST Extension])
  PHP_NEW_EXTENSION(test, test.c, $ext_shared)
fi

File: php_test.h

#ifndef PHP_TEST_H
#define PHP_TEST_H 1

#define PHP_TEST_EXT_VERSION "1.0"
#define PHP_TEST_EXT_EXTNAME "test"

PHP_FUNCTION(getaddress4);
PHP_FUNCTION(getaddress);

extern zend_module_entry test_module_entry;
#define phpext_test_ptr &test_module_entry

#endif

File: test.c

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_test.h"

ZEND_BEGIN_ARG_INFO_EX(func_args, 1, 0, 0)
ZEND_END_ARG_INFO()

static function_entry test_functions[] = {
    PHP_FE(getaddress4, func_args)
    PHP_FE(getaddress, func_args)
    {NULL, NULL, NULL}
};

zend_module_entry test_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    PHP_TEST_EXT_EXTNAME,
    test_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
#if ZEND_MODULE_API_NO >= 20010901
    PHP_TEST_EXT_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_TEST
ZEND_GET_MODULE(test)
#endif

PHP_FUNCTION(getaddress4)
{
    zval *var1;
    zval *var2;
    zval *var3;
    zval *var4;
    char r[500];
    if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aaaa", &var1, &var2, &var3, &var4) == FAILURE ) {
      RETURN_NULL();
    }
    sprintf(r, "\n%p - %p - %p - %p\n%p - %p - %p - %p", var1, var2, var3, var4, Z_ARRVAL_P(var1), Z_ARRVAL_P(var2), Z_ARRVAL_P(var3), Z_ARRVAL_P(var4) );
    RETURN_STRING(r, 1);
}

PHP_FUNCTION(getaddress)
{
    zval *var;
    char r[100];
    if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &var) == FAILURE ) {
      RETURN_NULL();
    }
    sprintf(r, "%p", Z_ARRVAL_P(var));
    RETURN_STRING(r, 1);
}

Then all you have to do is phpize it, config it, and make it. Add a "extension=/path/to/so/file/modules/test.so" to your php.ini file. And finally, restart the web server, just in case.

<?php
  $x = array("123"=>"123");
  $w = $x;
  $y = $x;
  $z = &$x;
  var_dump(getaddress4($w,$x,$y,$z));
  var_dump(getaddress($w));
  var_dump(getaddress($x));
  var_dump(getaddress($y));
  var_dump(getaddress($z));
?>

Returns(at least for me, your memory addresses will probably be different)

string '
0x9efeb0 - 0x9effe0 - 0x9ef8c0 - 0x9efeb0
0x9efee0 - 0x9f0010 - 0x9ed790 - 0x9efee0' (length=84)

string '0x9efee0' (length=8)

string '0x9f0010' (length=8)

string '0x9ed790' (length=8)

string '0x9efee0' (length=8)

Thanks to Artefacto for pointing this out, but my original code was passing the arrays by value, so thereby was recreating arrays including the referenced-one, and giving you bad memory values. I have since changed the code to force all params to be passed by reference. This will allow references, arrays, and object, to be passed in unmolested by the php engine. $w/$z are the same thing, but $w/$x/$y are not. The old code, actually showed the reference breakage and the fact that the memory addresses would change or match when all variables were passed in vs multiple calls to the same function. This was because PHP would reuse the same memory when doing multiple calls. Comparing the results of the original function would be useless. The new code should fix this problem.

FYI - I'm using php 5.3.2.

软糯酥胸 2024-10-07 12:56:03

PHP 中的引用是通过不同名称访问相同变量内容的一种方法。它们不像 C 指针;例如,您不能使用它们执行指针算术,它们不是实际的内存地址, 等等。

结论:不,你不能

来自:http://www.php。 net/manual/en/language.references.whatare.php

References in PHP are a means to access the same variable content by different names. They are not like C pointers; for instance, you cannot perform pointer arithmetic using them, they are not actual memory addresses, and so on.

Conclusion: No, you can not

From: http://www.php.net/manual/en/language.references.whatare.php

神魇的王 2024-10-07 12:56:03

你的问题实际上有点误导。 “指向相同的内存位置”和“是相同的数组”(对我来说意味着是引用,至少在 PHP 中)不是同一件事。

内存位置指的是指针。 PHP 中不提供指针。引用不是指针。

无论如何,如果您想检查 $b 实际上是否是 $a 的引用,这是您可以获得的最接近实际答案的结果:

function is_ref_to(&$a, &$b) {
    if (is_object($a) && is_object($b)) {
        return ($a === $b);
    }

    $temp_a = $a;
    $temp_b = $b;

    $key = uniqid('is_ref_to', true);
    $b = $key;

    if ($a === $key) $return = true;
    else $return = false;

    $a = $temp_a;
    $b = $temp_b;
    return $return; 
}

$a = array('foo');
$b = array('foo');
$c = &$a;
$d = $a;

var_dump(is_ref_to($a, $b)); // false
var_dump(is_ref_to($b, $c)); // false
var_dump(is_ref_to($a, $c)); // true
var_dump(is_ref_to($a, $d)); // false
var_dump($a); // is still array('foo')

Your question is actually a bit misleading. "point to the same memory location" and "are the same array" (which to me means is a reference to, at least in PHP) are not the same thing.

Memory locations refers to pointers. Pointers are not available in PHP. References are not pointers.

Anyway, if you want to check if $b is in fact a reference of $a, this is the closest you can get to an actual answer:

function is_ref_to(&$a, &$b) {
    if (is_object($a) && is_object($b)) {
        return ($a === $b);
    }

    $temp_a = $a;
    $temp_b = $b;

    $key = uniqid('is_ref_to', true);
    $b = $key;

    if ($a === $key) $return = true;
    else $return = false;

    $a = $temp_a;
    $b = $temp_b;
    return $return; 
}

$a = array('foo');
$b = array('foo');
$c = &$a;
$d = $a;

var_dump(is_ref_to($a, $b)); // false
var_dump(is_ref_to($b, $c)); // false
var_dump(is_ref_to($a, $c)); // true
var_dump(is_ref_to($a, $d)); // false
var_dump($a); // is still array('foo')
苄①跕圉湢 2024-10-07 12:56:03
        function check(&$a,&$b){
            // perform first basic check, if both have different values
            // then they're definitely not the same.
            if($a!==$b)return false;
            // backup $a into $c
            $c=$a;
            // get some form of opposite to $a
            $a=!$a;
            // compare $a and $b, if both are the same thing,
            // this should be true
            $r=($a===$b);
            // restore $a from $c
            $a=$c;
            // return result
            return $r;
        }

        $a=(object)array('aaa'=>'bbb'); $b=&$a;
        echo check($a,$b) ? 'yes' : 'no'; // yes
        $c='aaa'; $d='aaa';
        echo check($c,$d) ? 'yes' : 'no'; // no
        $e='bbb'; $f='ccc';
        echo check($e,$f) ? 'yes' : 'no'; // no

“check”函数在 2 分钟左右创建完成。它假设如果您更改引用的值,第二个引用也将具有新添加的值。
此函数仅适用于变量。您可以将它用于常量值、函数返回(除非通过引用)等。

编辑:在测试过程中,我最初遇到了一些困惑。我不断重复使用相同的变量名称($a 和 $b),这导致所有条件均为“是”。原因如下:

$a='aaa'; $b=&$a;     // a=aaa b=aaa
$a='ccc'; $b='ddd';   // a=ddd b=ddd   <= a is not ccc!

为了纠正这个问题,我给了它们一个不同的名称:

$a='aaa'; $b=&$a;     // a=aaa b=aaa
$c='ccc'; $d='ddd';   // c=ccc d=ddd   <= c is now correct

编辑:为什么答案是“是”而不是“否”

PHP 不会通过脚本显示指针信息(也不会指针操作等) 。
但是,它确实允许使用引用运算符“&”来完成别名变量(引用)。
特征通常存在于指针中,这解释了普遍的混乱。
也就是说,指针不是别名。

然而,如果我们看到原来的问题,这个人想知道 $a 是否与 $b 相同,而不是在内存中找到 $a (或 $b)。前面的要求适用于引用和指针,而后面的要求仅适用于指针。

        function check(&$a,&$b){
            // perform first basic check, if both have different values
            // then they're definitely not the same.
            if($a!==$b)return false;
            // backup $a into $c
            $c=$a;
            // get some form of opposite to $a
            $a=!$a;
            // compare $a and $b, if both are the same thing,
            // this should be true
            $r=($a===$b);
            // restore $a from $c
            $a=$c;
            // return result
            return $r;
        }

        $a=(object)array('aaa'=>'bbb'); $b=&$a;
        echo check($a,$b) ? 'yes' : 'no'; // yes
        $c='aaa'; $d='aaa';
        echo check($c,$d) ? 'yes' : 'no'; // no
        $e='bbb'; $f='ccc';
        echo check($e,$f) ? 'yes' : 'no'; // no

The function "check" was created in 2 mins or so. It assumes that if you change a reference's value, a second reference would have the newly add value as well.
This function works on variables only. You can use it against constant value, function returns (unless by reference) etc.

Edit: During testing, I had some initial confusion. I kept reusing the same variable names ($a and $b) which resulted in all the conditionals being "yes". Here's why:

$a='aaa'; $b=&$a;     // a=aaa b=aaa
$a='ccc'; $b='ddd';   // a=ddd b=ddd   <= a is not ccc!

To correct the issue, I gave them a different name:

$a='aaa'; $b=&$a;     // a=aaa b=aaa
$c='ccc'; $d='ddd';   // c=ccc d=ddd   <= c is now correct

Edit: Why the answer is "yes" and not "no"

PHP does not reveal pointer information through scripting (neither pointer manipulation etc).
However, it does allow alias variables (references), done by using the reference operator '&'.
Feature is typically found in pointers, which explains the general confusion.
That said, pointers are not aliases.

However, if we see the original question, the person wanted to know if $a is the same as $b, not where in the memory $a (or $b) is found. Whereas the earlier requirement applies to both references and pointers, the later one only applies to pointers.

司马昭之心 2024-10-07 12:56:03

首先,你的问题含糊不清。它可能意味着几个不同的事情:

  • 变量是否具有相同的内容?为此,您可以使用===
  • 变量在内部使用相同的内存吗?
  • 这些变量是否在同一参考集中?即,给定两个变量 $a$b,如果我更改 $a,它会更改 $b >?

第二个答案的答案并不容易确定。杰里米·沃尔顿(Jeremy Walton)的答案有一个重要的问题——他的函数按值接收,因此如果你向它传递一个引用,你就会强制分离并获得一个新的临时值的地址。您可以使函数通过引用接收参数,但是这样您就会遇到相反的问题 - 如果您传递一个值(引用计数 >= 2),您也会强制分离。

更重要的是,第二个问题是一个无关紧要的内部细节。考虑以下脚本:

$a = 1;
$b = $a; //addresses of $a and $b are the same
function force_sep(&$a) { }
force_sep($b);
//force_sep is a no-op, but it forced a separation; now addresses are not equal

所以重要的问题是第三个问题。不幸的是,没有直接的方法来确定这一点。这已被多次要求;例如,请参阅此请求

但是,有几个选项:

  • 您可以接收变量的名称并在符号表中查找它。这也使得 xdebug_debug_zval 比有缺陷的 debug_zval_dump。这是在 EG(active_symbol_table) 中对简单变量的简单查找(但如果您想包含对象属性和尺寸等,则会变得更加复杂),这也将允许您实现以下解决方案:第二个问题。
  • 您还可以修改 Jeremy Walton 的答案,使函数通过引用接收(您需要 arginfo 结构)并同时接收两个值。同时接收它们可以避免由于重用内存地址而导致的误报(尽管这是否是一个问题取决于函数的使用;另一方面,Jeremy Walton 的函数总是遇到这个问题,当接收参考资料——如果有必要,我可以详细说明这一点,但请参阅他的答案下的评论)。
  • netcoder 的答案虽然有些黑客,但也有效。这个想法是通过引用接收两个变量,更改一个变量,然后查看另一个变量是否更改,最后恢复值。

First, your question is vague. It can mean several different things:

  • Do the variables have the same content? For this, you can use ===.
  • Do the variables use internally the same memory?
  • Are these variables in the same reference set? I.e., given two variables, $a and $b, if I change $a, will it change $b?

The answer to the second answer is not easy to determine. Jeremy Walton's answer has one significant problem -- his function receives by value, so if you pass it a reference, you force a separation and get the address of a new temporary value. You could make the function receive the parameter by reference, but then you'd have the opposite problem -- if you passed a value (with refcount >= 2), you would also force a separation.

More importantly, the second question is an irrelevant internal detail. Consider the following script:

$a = 1;
$b = $a; //addresses of $a and $b are the same
function force_sep(&$a) { }
force_sep($b);
//force_sep is a no-op, but it forced a separation; now addresses are not equal

So the important question is the third one. Unfortunately, there is no straightforward way to determine this. This has been requested several times; see e.g. this request.

However, there are a few options:

  • You could to receive the name of the variable and look it up in the symbol table. This is also what makes xdebug_debug_zval much more interesting than the flawed debug_zval_dump. This is a simple lookup in EG(active_symbol_table) for simple variables (but would get more complex if you wanted to include object properties and dimensions etc.), and this would also allow you to implement a solution for the 2nd question.
  • You could also modify Jeremy Walton's answer to make the function receive by reference (you'd need an arginfo structure) and receive the two values at the same time. Receiving them at the same time can avoid false positives due to reused memory addresses (though whether it's a problem depends on the usage of the function; on the other hand, Jeremy Walton's function always suffers from this problem when receiving references -- I can elaborate on this if necessary, but see my comment under his answer).
  • netcoder's answer, although hackish, also works. The idea is to receive two variables by reference, change one, and see if the other one changed, restoring the values in the end.
始终不够 2024-10-07 12:56:03

PHP 中的参考比较

我知道这个问题已经很老了,但这仍然相关 - 这就是我最终来到这里的原因。可能有多种方法可以对此进行测试,但我想出了其他几种方法。

PHP 7.4 引用相等性测试

ReflectionReference 为数组元素提供引用 id:

function is_same(&$a, &$b): bool {
  $_ = [ &$a, &$b ];
  return
    \ReflectionReference::fromArrayElement($_, 0)->getId() ===
    \ReflectionReference::fromArrayElement($_, 1)->getId();
}

PHP 版本 5、7 和 8

该函数将依靠 PHP 序列化检测循环引用的事实来发现实际引用。缺点是对于大数组,它会暂时需要内存和时间来序列化数据。对于大数组,最好使用下面的实用数组相等性测试。

function is_same(&$a, &$b) {
    $_ = [ &$a, &$b ];
    // PHP >= 7.4
    if (\class_exists(\ReflectionReference::class)) {
      return
        \ReflectionReference::fromArrayElement($_, 0)->getId() ===
        \ReflectionReference::fromArrayElement($_, 1)->getId();
    }

    // Faster, for objects
    if (\is_object($a) && \is_object($b) && $a === $b) return true;

    // Stop if they aren't identical, this is much faster.
    if ($a !== $b) return false;

    // Resources can't be serialized
    if (\is_resource($a) && \is_resource($b) && "".$a === "".$b) return true;

    // Serialization supports references, so we utilize that
    return \substr(\serialize($_), -5) === 'R:2;}';
}

内存友好的 PHP < 7.4 数组引用检查

这个测试应该在不浪费太多内存的情况下完成任务。一个副作用是 PHP 使用写时复制来节省数组内存 - 因此当此函数追加到数组时,它将触发该机制。

function array_is_same(array &$a, array &$b): bool {
  // Fastest test first
  if ($a !== $b) {
    return false;
  }
  // Then the reference test
  try {
    // Need a unique key
    while (
      array_key_exists($key = '#! '.mt_rand(PHP_INT_MIN, PHP_INT_MAX), $a) || 
      array_key_exists($key, $b)
    );
    $a[$key] = true;
    return isset($b[$key]);
  } finally {
    // cleanup
    unset($a[$key], $b[$key]);
  }
}

Reference comparison in PHP

I know the question is old, but this is still relevant - which is why I ended up here. There are probably several ways to test this, but I came up with a couple of other methods.

PHP 7.4 reference equality test

ReflectionReference provides a reference id for array elements:

function is_same(&$a, &$b): bool {
  $_ = [ &$a, &$b ];
  return
    \ReflectionReference::fromArrayElement($_, 0)->getId() ===
    \ReflectionReference::fromArrayElement($_, 1)->getId();
}

PHP version 5, 7 and 8

This function will spot an actual reference, by relying on the fact that PHP serialization detects circular references. The downside is that for big arrays it will temporary need memory and time to serialize the data. For big arrays it may be better to use the pragmatic array equality test below.

function is_same(&$a, &$b) {
    $_ = [ &$a, &$b ];
    // PHP >= 7.4
    if (\class_exists(\ReflectionReference::class)) {
      return
        \ReflectionReference::fromArrayElement($_, 0)->getId() ===
        \ReflectionReference::fromArrayElement($_, 1)->getId();
    }

    // Faster, for objects
    if (\is_object($a) && \is_object($b) && $a === $b) return true;

    // Stop if they aren't identical, this is much faster.
    if ($a !== $b) return false;

    // Resources can't be serialized
    if (\is_resource($a) && \is_resource($b) && "".$a === "".$b) return true;

    // Serialization supports references, so we utilize that
    return \substr(\serialize($_), -5) === 'R:2;}';
}

Memory friendly PHP < 7.4 array reference checking

This test should do the deed without wasting too much memory. A side effect is that PHP uses copy-on-write to save memory on arrays - so when this function appends to the array, it will trigger that mechanism.

function array_is_same(array &$a, array &$b): bool {
  // Fastest test first
  if ($a !== $b) {
    return false;
  }
  // Then the reference test
  try {
    // Need a unique key
    while (
      array_key_exists($key = '#! '.mt_rand(PHP_INT_MIN, PHP_INT_MAX), $a) || 
      array_key_exists($key, $b)
    );
    $a[$key] = true;
    return isset($b[$key]);
  } finally {
    // cleanup
    unset($a[$key], $b[$key]);
  }
}
仄言 2024-10-07 12:56:03
function var_name(&$ref){
    foreach($GLOBALS as $key => $val){
       if($val === $ref) return $key;
    }
}

这是未经测试的,但据我所知,php,变量在加载到系统中时被添加到全局变量中,因此它们相同的第一次出现应该是原始变量,但如果你有 2 个变量完全相同我'我不确定它会如何反应

function var_name(&$ref){
    foreach($GLOBALS as $key => $val){
       if($val === $ref) return $key;
    }
}

This is untested but what i know of php, vars are added to the GLOBALS as they are are loaded into the system, so the first occurance where they are identical should be the original var, but if you have 2 Variables Exactly the same i'm not sure how it would react

青春有你 2024-10-07 12:56:03
 $a["unqiue-thing"] = 1;
 if($b["unique-thing"] == 1) // a and b are the same
 $a["unqiue-thing"] = 1;
 if($b["unique-thing"] == 1) // a and b are the same
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文