집 >
백엔드 개발 >
PHP 튜토리얼 >
[번역][php 확장 개발 및 임베디드] 2장 - 변수의 내부와 외부
[번역][php 확장 개발 및 임베디드] 2장 - 변수의 내부와 외부
黄舟
풀어 주다: 2023-03-05 16:08:02
원래의
1428명이 탐색했습니다.
변수의 내부와 외부
모든 프로그래밍 언어에 공통된 기능 중 하나는 정보를 저장하고 검색하는 것입니다. PHP도 예외는 아니지만 사용하기 전에 모든 변수를 정의해야 합니다. 고정되어 있지만 PHP를 사용하면 프로그래머가 변수를 사용할 때 변수를 생성할 수 있고, 어떤 유형의 언어로도 표현할 수 있는 정보를 저장할 수 있습니다. 또한 필요할 때 자동으로 변수 유형을 변환할 수도 있습니다.
사용자를 사용했기 때문에- space PHP, 이 개념이 "약한 타이핑"이라는 것을 알아야 합니다. 이 장에서는 이 정보를 PHP의 상위 언어인 c(C의 유형은 엄격함)에서 볼 수 있습니다.
물론, 어떻게 인코딩되나요? 데이터 인코딩은 작업의 절반에 불과합니다. 이러한 모든 정보를 추적하려면 각 변수에도 레이블과 컨테이너가 필요합니다. 사용자 공간 관점에서 이를 변수 이름과 범위의 개념으로 생각할 수 있습니다.
데이터 유형
PHP의 데이터 저장 단위는 Zend Value라고도 하는 zval입니다. Zend/zend.h에 정의된 4개의 멤버 본문만 있는 구조이며 형식은 다음과 같습니다.
우리는 대부분의 멤버의 기본 저장 유형을 직관적으로 추측할 수 있습니다: 부호 없는 정수의 refcount, 부호 없는 문자의 유형 및 값 그리고 값 멤버는 실제로 PHP5에서 공용체로 정의된 구조입니다.
typedef union _zvalue_value {
long lval;
double dval;
struct {
char *val;
int len;
} str;
HashTable *ht;
zend_object_value obj;
} zvalue_value;
로그인 후 복사
Union을 사용하면 Zend는 단일 통합 구조를 사용하여 다양한 유형의 데이터를 PHP 변수에 저장할 수 있습니다.
zend는 현재 다음에 나열된 8개의 데이터 유형을 정의합니다. 테이블:
유형 값
목적
IS_NULL
이 유형은 처음 사용될 때까지 초기화되지 않은 변수에 자동으로 할당됩니다. 명시적 할당을 위해 내장된 사용자 공간 NULL 상수를 사용할 수도 있습니다. 이 변수 유형은 특별한 "데이터 없음" 유형을 제공합니다. 이는 부울 FALSE 및 정수 0과 다릅니다.
IS_BOOL
부울 변수는 if와 같은 사용자 공간 제어 구조의 두 가지 가능한 상태 중 하나를 가질 수 있습니다. /while/ternary/for 및 그 사이에 있는 다른 조건식은 부울 유형입니다.
IS_DOUBLE
부동 소수점 데이터 유형은 호스트 시스템의 부호 있는 이중 데이터 유형 부동 소수점 숫자는 정확한 정밀도로 저장되지 않습니다. 공식을 사용하여 값의 소수 부분의 유한 정밀도를 나타냅니다(주석: 부동 소수점 숫자는 부호, 가수 - 분수 부분, 지수. 부동 소수점 숫자의 값 = 부호 * 가수 * 2^지수 - BSD 라이브러리 함수 매뉴얼: float(3)) 이 표기법을 사용하면 컴퓨터가 다양한 값(양수 또는 음수): 2.225*10^(-308) ~ 1.798*10^(8바이트 308로 표시 가능) 불행히도 평가되는 숫자의 실제 십진수 값이 항상 이진 분수만큼 깔끔하게 저장되는 것은 아닙니다. , 십진수 표현식 0.5는 정확한 이진수 값 0.1로 변환되는 반면, 십진수 표현식 0.8은 이진수로 변환되는 것은 0.1100110011의 무한 루프입니다.... 십진수로 다시 변환하면 버려진 이진수 비트는 복구할 수 없습니다. 마찬가지로 1/3을 10진수 0.333333으로 변환한다고 생각할 수 있습니다. 두 값은 매우 유사하지만 3 * 0.333333은 1.0과 같지 않기 때문에 종종 혼동을 줍니다. (이러한 범위 제한은 일반적으로 32비트 플랫폼을 기반으로 하며 시스템 범위에 따라 다를 수 있습니다.)
IS_STRING
가장 일반적입니다. PHP의 데이터 유형은 문자열이며 숙련된 C 프로그래머가 예상하는 방식으로 저장됩니다. 블록을 할당하는 것으로 충분합니다. 문자열의 모든 바이트/문자의 메모리를 저장하고 호스트 zval의 문자열에 대한 포인터를 저장합니다.
Zval 구조에서는 PHP 문자열의 길이가 항상 명시적이므로 문자열이 잘리지 않고 NULL 바이트를 포함할 수 있다는 점에 주목할 필요가 있습니다. 이렇게 하면 모든 유형의 바이너리 데이터를 안전하게 포함할 수 있습니다.
PHP 문자열에 할당된 총 메모리 양은 항상 최소화됩니다. 길이에 1을 더한 것입니다. 마지막 바이트는 종료 NULL을 저장합니다. 문자이므로 바이너리 안전 함수는 문제가 되지 않습니다. 문자열 포인터를 직접 전달할 수 있습니다.
IS_ARRAY
배열은 C의 배열 개념과 달리 다른 변수를 구성하는 기능만 하는 특수 목적 변수입니다. 단일 유형의 데이터(예: zval arrayofzvals[];) 실제로 PHP의 배열은 데이터 버킷의 복잡한 모음이며 내부는 HashTable입니다. 각 HashTable 요소(버킷)에는 태그와 데이터라는 두 가지 해당 정보가 포함되어 있습니다. . PHP 배열의 응용 시나리오에서 태그는 연결된 배열의 키 또는 값입니다.
IS_OBJECT
<🎜 객체에는 메소드, 액세스 수정자, 범위 상수 및 특수 이벤트 핸들러 추가 외에도 다중 요소 데이터 저장소 배열이 있습니다. 확장 개발자로서 php4 및 php4에서 동등한 객체 지향 코드를 작성하는 것은 큰 도전입니다. php5. Zend Engine 1(php4)과 Zend Engine 2(php5) 사이에 내부 개체 모델이 많이 변경되었기 때문에 큰 도전입니다.
IS_RESOURCE
여기 예를 들어 stdio의 FILE 포인터 또는 libmysqlclient의 연결 핸들은 단순히 스칼라 값 배열에 매핑될 수 없습니다. 그렇지 않으면 사용자 공간 스크립트를 보호하기 위해 의미를 잃게 됩니다. 작성자는 이러한 문제를 처리할 필요가 없습니다. PHP는 범중국어 리소스 데이터 유형을 제공하므로 9장 "리소스 데이터 유형"에서 리소스 유형의 구현 세부 사항을 다룰 것입니다. . 알았어.
void describe_zval(zval *foo)
{
if (foo->type == IS_NULL) {
php_printf("The variable is NULL");
} else {
php_printf("The variable is of type %d", foo->type);
}
}
void describe_zval(zval *foo)
{
if (Z_TYPE_P(foo) == IS_NULL) {
php_printf("The variable is NULL");
} else {
php_printf("The variable is of type %d",
Z_TYPE_P(foo));
}
}
void display_values(zval boolzv, zval *longpzv,
zval **doubleppzv)
{
if (Z_TYPE(boolzv) == IS_BOOL) {
php_printf("The value of the boolean is: %s\n",
Z_BVAL(boolzv) ? "true" : "false");
}
if (Z_TYPE_P(longpzv) == IS_LONG) {
php_printf("The value of the long is: %ld\n",
Z_LVAL_P(longpzv));
}
if (Z_TYPE_PP(doubleppzv) == IS_DOUBLE) {
php_printf("The value of the double is: %f\n",
Z_DVAL_PP(doubleppzv));
}
}
{
zval **fooval;
if (zend_hash_find(EG(active_symbol_table),
"foo", sizeof("foo"),
(void**)&fooval) == SUCCESS) {
php_printf("Got the value of $foo!");
} else {
php_printf("$foo is not defined.");
}
}
void display_zval(zval *value)
{
switch (Z_TYPE_P(value)) {
case IS_NULL:
/* NULLs are echoed as nothing */
break;
case IS_BOOL:
if (Z_BVAL_P(value)) {
php_printf("1");
}
break;
case IS_LONG:
php_printf("%ld", Z_LVAL_P(value));
break;
case IS_DOUBLE:
php_printf("%f", Z_DVAL_P(value));
break;
case IS_STRING:
PHPWRITE(Z_STRVAL_P(value), Z_STRLEN_P(value));
break;
case IS_RESOURCE:
php_printf("Resource #%ld", Z_RESVAL_P(value));
break;
case IS_ARRAY:
php_printf("Array");
break;
case IS_OBJECT:
php_printf("Object");
break;
default:
/* Should never happen in practice,
* but it's dangerous to make assumptions
*/
php_printf("Unknown");
break;
}
}