D 프로그래밍-포인터
D 프로그래밍 포인터는 배우기 쉽고 재미 있습니다. 일부 D 프로그래밍 작업은 포인터를 사용하여 더 쉽게 수행되며 동적 메모리 할당과 같은 다른 D 프로그래밍 작업은 포인터없이 수행 할 수 없습니다. 간단한 포인터가 아래에 나와 있습니다.
변수를 직접 가리키는 대신 포인터는 변수의 주소를 가리 킵니다. 아시다시피 모든 변수는 메모리 위치이고 모든 메모리 위치에는 메모리의 주소를 나타내는 앰퍼샌드 (&) 연산자를 사용하여 액세스 할 수있는 주소가 정의되어 있습니다. 정의 된 변수의 주소를 인쇄하는 다음을 고려하십시오-
import std.stdio;
void main () {
int var1;
writeln("Address of var1 variable: ",&var1);
char var2[10];
writeln("Address of var2 variable: ",&var2);
}
위의 코드가 컴파일되고 실행되면 다음과 같은 결과가 생성됩니다.
Address of var1 variable: 7FFF52691928
Address of var2 variable: 7FFF52691930
포인터 란?
ㅏ pointer값이 다른 변수의 주소 인 변수입니다. 다른 변수 나 상수와 마찬가지로 포인터를 사용하려면 먼저 포인터를 선언해야합니다. 포인터 변수 선언의 일반적인 형식은 다음과 같습니다.
type *var-name;
여기, type포인터의 기본 유형입니다. 유효한 프로그래밍 유형이어야하며var-name포인터 변수의 이름입니다. 포인터를 선언하는 데 사용한 별표는 곱하기에 사용하는 것과 동일한 별표입니다. 하나; 이 문에서 별표는 변수를 포인터로 지정하는 데 사용됩니다. 다음은 유효한 포인터 선언입니다-
int *ip; // pointer to an integer
double *dp; // pointer to a double
float *fp; // pointer to a float
char *ch // pointer to character
정수, 부동 소수점, 문자 등 모든 포인터 값의 실제 데이터 유형은 메모리 주소를 나타내는 긴 16 진수와 동일합니다. 서로 다른 데이터 유형의 포인터 간의 유일한 차이점은 포인터가 가리키는 변수 또는 상수의 데이터 유형입니다.
D 프로그래밍에서 포인터 사용
포인터를 매우 자주 사용할 때 중요한 작업은 거의 없습니다.
포인터 변수를 정의합니다.
변수의 주소를 포인터에 할당
마지막으로 포인터 변수에서 사용할 수있는 주소의 값에 액세스합니다.
이것은 단항 연산자를 사용하여 수행됩니다. *피연산자가 지정한 주소에있는 변수의 값을 반환합니다. 다음 예제는 이러한 작업을 사용합니다-
import std.stdio;
void main () {
int var = 20; // actual variable declaration.
int *ip; // pointer variable
ip = &var; // store address of var in pointer variable
writeln("Value of var variable: ",var);
writeln("Address stored in ip variable: ",ip);
writeln("Value of *ip variable: ",*ip);
}
위의 코드가 컴파일되고 실행되면 다음과 같은 결과가 생성됩니다.
Value of var variable: 20
Address stored in ip variable: 7FFF5FB7E930
Value of *ip variable: 20
널 포인터
할당 할 정확한 주소가없는 경우 항상 포인터 NULL을 포인터 변수에 할당하는 것이 좋습니다. 이것은 변수 선언시 수행됩니다. 널이 할당 된 포인터를null 바늘.
널 포인터는 iostream을 포함한 여러 표준 라이브러리에 정의 된 값이 0 인 상수입니다. 다음 프로그램을 고려하십시오-
import std.stdio;
void main () {
int *ptr = null;
writeln("The value of ptr is " , ptr) ;
}
위의 코드가 컴파일되고 실행되면 다음과 같은 결과가 생성됩니다.
The value of ptr is null
대부분의 운영 체제에서는 해당 메모리가 운영 체제에 의해 예약되어 있기 때문에 프로그램이 주소 0의 메모리에 액세스 할 수 없습니다. 하나; 메모리 주소 0은 특별한 의미가 있습니다. 포인터가 액세스 가능한 메모리 위치를 가리 키도록 의도되지 않았 음을 나타냅니다.
관례 적으로 포인터에 널 (영) 값이 포함되어 있으면 아무 것도 가리키는 것으로 간주되지 않습니다. 널 포인터를 확인하려면 다음과 같이 if 문을 사용할 수 있습니다.
if(ptr) // succeeds if p is not null
if(!ptr) // succeeds if p is null
따라서, 사용하지 않는 모든 포인터에 널값이 주어지고 널 포인터의 사용을 피하면 초기화되지 않은 포인터의 우발적 오용을 피할 수 있습니다. 대부분의 경우 초기화되지 않은 변수에는 일부 정크 값이 포함되어 프로그램을 디버그하기가 어려워집니다.
포인터 산술
포인터에 사용할 수있는 산술 연산자는 ++,-, + 및-네 가지입니다.
포인터 산술을 이해하기 위해 다음과 같은 정수 포인터를 고려해 보겠습니다. ptr, 주소 1000을 가리 킵니다. 32 비트 정수를 가정하고 포인터에 대해 다음과 같은 산술 연산을 수행해 보겠습니다.
ptr++
다음 ptrptr이 증가 할 때마다 다음 정수를 가리 키기 때문에 1004 위치를 가리 킵니다. 이 작업은 메모리 위치의 실제 값에 영향을주지 않고 포인터를 다음 메모리 위치로 이동합니다.
만약 ptr 주소가 1000 인 문자를 가리키면 다음 문자를 1001에서 사용할 수 있으므로 위의 작업은 1001 위치를 가리 킵니다.
포인터 증가
상수 포인터이기 때문에 증가 할 수없는 배열 이름과 달리 변수 포인터가 증가 할 수 있기 때문에 우리 프로그램에서 배열 대신 포인터를 사용하는 것을 선호합니다. 다음 프로그램은 배열의 각 후속 요소에 액세스하기 위해 변수 포인터를 증가시킵니다-
import std.stdio;
const int MAX = 3;
void main () {
int var[MAX] = [10, 100, 200];
int *ptr = &var[0];
for (int i = 0; i < MAX; i++, ptr++) {
writeln("Address of var[" , i , "] = ",ptr);
writeln("Value of var[" , i , "] = ",*ptr);
}
}
위의 코드가 컴파일되고 실행되면 다음과 같은 결과가 생성됩니다.
Address of var[0] = 18FDBC
Value of var[0] = 10
Address of var[1] = 18FDC0
Value of var[1] = 100
Address of var[2] = 18FDC4
Value of var[2] = 200
포인터 대 배열
포인터와 배열은 밀접한 관련이 있습니다. 그러나 포인터와 배열은 완전히 상호 교환 할 수 없습니다. 예를 들어, 다음 프로그램을 고려하십시오.
import std.stdio;
const int MAX = 3;
void main () {
int var[MAX] = [10, 100, 200];
int *ptr = &var[0];
var.ptr[2] = 290;
ptr[0] = 220;
for (int i = 0; i < MAX; i++, ptr++) {
writeln("Address of var[" , i , "] = ",ptr);
writeln("Value of var[" , i , "] = ",*ptr);
}
}
위 프로그램에서 두 번째 요소를 설정하는 var.ptr [2]와 0 번째 요소를 설정하는 데 사용되는 ptr [0]을 볼 수 있습니다. 증가 연산자는 ptr과 함께 사용할 수 있지만 var에는 사용할 수 없습니다.
위의 코드가 컴파일되고 실행되면 다음과 같은 결과가 생성됩니다.
Address of var[0] = 18FDBC
Value of var[0] = 220
Address of var[1] = 18FDC0
Value of var[1] = 100
Address of var[2] = 18FDC4
Value of var[2] = 290
포인터에 대한 포인터
포인터에 대한 포인터는 다중 간접 지정 또는 포인터 체인의 한 형태입니다. 일반적으로 포인터는 변수의 주소를 포함합니다. 포인터에 대한 포인터를 정의 할 때 첫 번째 포인터에는 아래와 같이 실제 값을 포함하는 위치를 가리키는 두 번째 포인터의 주소가 포함됩니다.
포인터에 대한 포인터 인 변수는 이와 같이 선언되어야합니다. 이름 앞에 별표를 추가하면됩니다. 예를 들어, 다음은 int 유형의 포인터에 대한 포인터를 선언하는 구문입니다.
int **var;
대상 값이 포인터에 대한 포인터에 의해 간접적으로 가리키는 경우 해당 값에 액세스하려면 아래 예제에서와 같이 별표 연산자를 두 번 적용해야합니다.
import std.stdio;
const int MAX = 3;
void main () {
int var = 3000;
writeln("Value of var :" , var);
int *ptr = &var;
writeln("Value available at *ptr :" ,*ptr);
int **pptr = &ptr;
writeln("Value available at **pptr :",**pptr);
}
위의 코드가 컴파일되고 실행되면 다음과 같은 결과가 생성됩니다.
Value of var :3000
Value available at *ptr :3000
Value available at **pptr :3000
함수에 포인터 전달
D를 사용하면 함수에 대한 포인터를 전달할 수 있습니다. 이를 위해 단순히 함수 매개 변수를 포인터 유형으로 선언합니다.
다음 간단한 예제는 함수에 대한 포인터를 전달합니다.
import std.stdio;
void main () {
// an int array with 5 elements.
int balance[5] = [1000, 2, 3, 17, 50];
double avg;
avg = getAverage( &balance[0], 5 ) ;
writeln("Average is :" , avg);
}
double getAverage(int *arr, int size) {
int i;
double avg, sum = 0;
for (i = 0; i < size; ++i) {
sum += arr[i];
}
avg = sum/size;
return avg;
}
위의 코드가 함께 컴파일되고 실행되면 다음 결과가 생성됩니다.
Average is :214.4
함수에서 포인터 반환
포인터를 사용하여 10 개의 숫자를 반환하는 다음 함수는 첫 번째 배열 요소의 주소를 의미합니다.
import std.stdio;
void main () {
int *p = getNumber();
for ( int i = 0; i < 10; i++ ) {
writeln("*(p + " , i , ") : ",*(p + i));
}
}
int * getNumber( ) {
static int r [10];
for (int i = 0; i < 10; ++i) {
r[i] = i;
}
return &r[0];
}
위의 코드가 컴파일되고 실행되면 다음과 같은 결과가 생성됩니다.
*(p + 0) : 0
*(p + 1) : 1
*(p + 2) : 2
*(p + 3) : 3
*(p + 4) : 4
*(p + 5) : 5
*(p + 6) : 6
*(p + 7) : 7
*(p + 8) : 8
*(p + 9) : 9
배열에 대한 포인터
배열 이름은 배열의 첫 번째 요소에 대한 상수 포인터입니다. 따라서 선언에서-
double balance[50];
balance배열 밸런스의 첫 번째 요소 주소 인 & balance [0]에 대한 포인터입니다. 따라서 다음 프로그램 조각은p 첫 번째 요소의 주소 balance −
double *p;
double balance[10];
p = balance;
배열 이름을 상수 포인터로 사용하는 것은 합법적이며 그 반대의 경우도 마찬가지입니다. 따라서 * (잔액 + 4)는 balance [4]에서 데이터에 액세스하는 합법적 인 방법입니다.
p에 첫 번째 요소의 주소를 저장하면 * p, * (p + 1), * (p + 2) 등을 사용하여 배열 요소에 액세스 할 수 있습니다. 다음 예는 위에서 설명한 모든 개념을 보여줍니다.
import std.stdio;
void main () {
// an array with 5 elements.
double balance[5] = [1000.0, 2.0, 3.4, 17.0, 50.0];
double *p;
p = &balance[0];
// output each array element's value
writeln("Array values using pointer " );
for ( int i = 0; i < 5; i++ ) {
writeln( "*(p + ", i, ") : ", *(p + i));
}
}
위의 코드가 컴파일되고 실행되면 다음과 같은 결과가 생성됩니다.
Array values using pointer
*(p + 0) : 1000
*(p + 1) : 2
*(p + 2) : 3.4
*(p + 3) : 17
*(p + 4) : 50