IT

배열의 주소는 C의 값과 어떻게 다릅니 까?

lottoking 2020. 5. 20. 08:12
반응형

배열의 주소는 C의 값과 어떻게 다릅니 까?


다음 코드 비트에서 포인터 값과 포인터 주소가 예상과 다릅니다.

그러나 배열 값과 주소는 그렇지 않습니다!

어떻게 이럴 수있어?

산출

my_array = 0022FF00
&my_array = 0022FF00
pointer_to_array = 0022FF00
&pointer_to_array = 0022FEFC
#include <stdio.h>

int main()
{
  char my_array[100] = "some cool string";
  printf("my_array = %p\n", my_array);
  printf("&my_array = %p\n", &my_array);

  char *pointer_to_array = my_array;
  printf("pointer_to_array = %p\n", pointer_to_array);
  printf("&pointer_to_array = %p\n", &pointer_to_array);

  printf("Press ENTER to continue...\n");
  getchar();
  return 0;
}

배열의 이름은 일반적으로 어레이의 첫 번째 요소의 주소로 평가되므로 array&array동일한 값이 (그러나 다른 유형이므로 array+1&array+1것이다 하지 어레이가 1 개 이상의 요소가 길면 동일).

이에 대한 두 가지 예외가 있습니다. 배열 이름이 피연산자 sizeof이거나 단항 &(주소) 인 경우 이름은 배열 객체 자체를 나타냅니다. 따라서 sizeof array포인터 크기가 아닌 전체 배열의 크기를 바이트 단위로 제공합니다.

로 정의 된 배열의 T array[size]경우 유형이 T *입니다. 증가시킬 때, 배열의 다음 요소로 이동합니다.

&array동일한 주소로 평가되지만 동일한 정의가 주어지면 유형의 포인터를 만듭니다. T(*)[size]즉, 단일 요소가 아닌 배열에 대한 포인터입니다. 이 포인터를 늘리면 단일 요소의 크기가 아닌 전체 배열의 크기가 추가됩니다. 예를 들어 다음과 같은 코드를 사용하십시오.

char array[16];
printf("%p\t%p", (void*)&array, (void*)(&array+1));

우리는 두 번째 포인터가 첫 번째 포인터보다 16 더 클 것으로 예상 할 수 있습니다 (16 문자 배열이므로). % p는 일반적으로 포인터를 16 진수로 변환하므로 다음과 같이 보일 수 있습니다.

0x12341000    0x12341010

배열 이름 ( my_array)이 배열에 대한 포인터와 다르기 때문 입니다. 배열 주소의 별칭이며 해당 주소는 배열 자체의 주소로 정의됩니다.

그러나 포인터는 스택에서 일반적인 C 변수입니다. 따라서 주소를 가져와 내부에있는 주소와 다른 값을 얻을 수 있습니다.

나는이 주제에 대해 여기에 썼다 .


식에서 배열의 이름을 사용하는 경우는 어드레스의 (의 피연산자가 아니면 C에서, (a 함수로 전달 포함) &) 오퍼레이터 또는 sizeof조작자가 그 감쇠 는 첫 번째 요소에 대한 포인터.

즉, 대부분의 상황 에서 유형과 가치 모두에 array해당 &array[0]합니다.

귀하의 예에서 printf에 전달할 때 붕괴되는 my_array유형 char[100]char*있습니다.

&my_arraytype char (*)[100](100의 배열을 가리키는 포인터 char)이 있습니다. 의 피연산자 &이므로 이것은 my_array첫 번째 요소에 대한 포인터로 즉시 붕괴되지 않는 경우 중 하나입니다 .

배열에 대한 포인터는 배열의 첫 번째 요소에 대한 포인터와 주소 값이 동일합니다. 배열 객체는 해당 요소의 연속적인 시퀀스이지만 배열에 대한 포인터는 요소에 대한 포인터와 다른 유형입니다. 그 배열. 이것은 두 가지 유형의 포인터에서 포인터 산술을 수행 할 때 중요합니다.

pointer_to_array입력 보유 char *즉 무엇으로 어레이의 첫 번째 요소를 가리 키도록 초기화를 - my_array이니셜 발현을 소멸 - 및 &pointer_to_array타입을 갖는다 char **(a 포인터에 포인터 char).

이러한 : my_array(부패 후 char*) &my_arraypointer_to_array어레이 또는 어레이 등의 첫 번째 요소 중 하나에 직접 포인트 모두 동일한 어드레스 값을 갖는다.


In the B programming language, which was the immediate predecessor to C, pointers and integers were freely interchangeable. The system would behave as though all of memory was a giant array. Each variable name had either a global or stack-relative address associated with it, for each variable name the only things the compiler had to keep track of was whether it was a global or local variable, and its address relative to the first global or local variable.

Given a global declaration like i; [there was no need to specify a type, since everything was an integer/pointer] would be processed by the compiler as: address_of_i = next_global++; memory[address_of_i] = 0; and a statement like i++ would be processed as: memory[address_of_i] = memory[address_of_i]+1;.

A declaration like arr[10]; would be processed as address_of_arr = next_global; memory[next_global] = next_global; next_global += 10;. Note that as soon as that declaration was processed, the compiler could immediately forget about arr being an array. A statement like arr[i]=6; would be processed as memory[memory[address_of_a] + memory[address_of_i]] = 6;. The compiler wouldn't care whether arr represented an array and i an integer, or vice versa. Indeed, it wouldn't care if they were both arrays or both integers; it would perfectly happily generate the code as described, without regard for whether the resulting behavior would likely be useful.

One of the goals of the C programming language was to be largely compatible with B. In B, the name of an array [called a "vector" in the terminology of B] identified a variable holding a pointer which was initially assigned to point to to the first element of an allocation of the given size, so if that name appeared in the argument list for a function, the function would receive a pointer to the vector. Even though C added "real" array types, whose name was rigidly associated with the address of the allocation rather than a pointer variable that would initially point to the allocation, having arrays decompose to pointers made code which declared a C-type array behave identically to B code which declared a vector and then never modified the variable holding its address.


The reason why my_array and &my_array result in the same address can be easily understood when you look at the memory layout of an array.

Let's say you have an array of 10 characters (instead the 100 in your code).

char my_array[10];

Memory for my_array looks something like:

+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+
^
|
Address of my_array.

In C/C++, an array decays to the pointer to the first element in an expression such as

printf("my_array = %p\n", my_array);

If you examine where the first element of the array lies you will see that its address is the same as the address of the array:

my_array[0]
|
v
+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+
^
|
Address of my_array[0].

Actually &myarray and myarray both are the base address.

If you want to see the difference instead of using

printf("my_array = %p\n", my_array);
printf("my_array = %p\n", &my_array);

use

printf("my_array = %s\n", my_array);
printf("my_array = %p\n", my_array);

참고URL : https://stackoverflow.com/questions/2528318/how-come-an-arrays-address-is-equal-to-its-value-in-c

반응형