IT

배열 이름이 포인터입니까?

lottoking 2020. 5. 14. 08:18
반응형

배열 이름이 포인터입니까?


배열의 이름이 C의 포인터입니까? 그렇지 않은 경우 배열의 이름과 포인터 변수의 차이점은 무엇입니까?


배열은 배열이고 포인터는 포인터이지만 대부분의 경우 배열 이름은 포인터 로 변환 됩니다. 자주 사용되는 용어는 포인터로 쇠퇴 한다는 것 입니다.

배열은 다음과 같습니다.

int a[7];

a 7 개의 정수를위한 공간을 포함하며, 다음과 같이 대입으로 값 중 하나에 값을 넣을 수 있습니다.

a[3] = 9;

다음은 포인터입니다.

int *p;

p정수를위한 공백을 포함하지 않지만 정수를위한 공백을 가리킬 수 있습니다. 예를 들어, 배열 a에서 첫 번째 장소 와 같은 장소 중 하나를 가리 키도록 설정할 수 있습니다 .

p = &a[0];

혼란스러운 점은 다음과 같이 쓸 수도 있다는 것입니다.

p = a;

이것은 배열의 내용을 포인터에 복사 하지 않습니다 (의미 한 것은 무엇이든). 대신 배열 이름 이 첫 번째 요소에 대한 포인터로 변환됩니다. 할당은 이전과 동일합니다.apa

이제 p배열과 비슷한 방식으로 사용할 수 있습니다 .

p[3] = 17;

이것이 작동하는 이유는 C의 배열 역 참조 연산자 [ ]가 포인터로 정의되기 때문입니다. x[y]수단 : 포인터로 시작 x, 단계 y에 어떤 포인터 포인트 후 앞으로 요소를, 다음이 무엇이든 걸릴. 포인터 산술 구문을 사용하여로 x[y]도 쓸 수 있습니다 *(x+y).

이것이 우리와 같은 일반 배열과 함께 작동 하려면 먼저 in a의 이름 aa[3]포인터로 변환해야합니다 (의 첫 번째 요소로 a). 그런 다음 3 단계 요소를 앞으로 진행하고 모든 요소를 ​​가져옵니다. 다시 말해, 배열에서 3 번째 위치에있는 요소를 가져옵니다. (첫 번째 요소의 번호는 0이므로 배열의 네 번째 요소는 어느 것입니까?)

따라서 요약하면 C 프로그램의 배열 이름은 (대부분의 경우) 포인터로 변환됩니다. 예외는 sizeof배열 에서 연산자를 사용할 때 입니다. a이 컨텍스트에서 포인터로 변환 된 경우 sizeof a실제 배열이 아닌 포인터 크기를 제공하므로 다소 쓸모가 없으므로 a배열 자체를 의미합니다.


배열을 값으로 사용하면 해당 이름은 첫 번째 요소의 주소를 나타냅니다.
배열을 값으로 사용하지 않으면 이름이 전체 배열을 나타냅니다.

int arr[7];

/* arr used as value */
foo(arr);
int x = *(arr + 1); /* same as arr[1] */

/* arr not used as value */
size_t bytes = sizeof arr;
void *q = &arr; /* void pointers are compatible with pointers to any object */

배열 유형의 표현식 (예 : 배열 이름)이 더 큰 표현식에 나타나 &거나 sizeof연산자 의 피연산자가 아닌 경우 배열 표현식의 유형은 "T의 N- 요소 배열"에서 "pointer to T"이고 표현식의 값은 배열에서 첫 번째 요소의 주소입니다.

간단히 말해 배열 이름은 포인터가 아니지만 대부분의 상황에서 포인터 인 것처럼 취급 됩니다 .

편집하다

의견의 질문에 대답 :

sizeof를 사용하면 배열의 요소 크기 만 계산합니까? 그런 다음 배열 "head"는 길이와 포인터에 대한 정보로 공간을 차지합니다 (일반 포인터보다 공간이 더 많이 사용됨)?

배열을 만들 때 할당 된 유일한 공간은 요소 자체를위한 공간입니다. 별도의 포인터 또는 메타 데이터를 위해 스토리지가 구체화되지 않습니다. 주어진

char a[10];

기억에 남는 것은

   +---+
a: |   | a[0]
   +---+ 
   |   | a[1]
   +---+
   |   | a[2]
   +---+
    ...
   +---+
   |   | a[9]
   +---+

The expression a refers to the entire array, but there's no object a separate from the array elements themselves. Thus, sizeof a gives you the size (in bytes) of the entire array. The expression &a gives you the address of the array, which is the same as the address of the first element. The difference between &a and &a[0] is the type of the result1 - char (*)[10] in the first case and char * in the second.

Where things get weird is when you want to access individual elements - the expression a[i] is defined as the result of *(a + i) - given an address value a, offset i elements (not bytes) from that address and dereference the result.

The problem is that a isn't a pointer or an address - it's the entire array object. Thus, the rule in C that whenever the compiler sees an expression of array type (such as a, which has type char [10]) and that expression isn't the operand of the sizeof or unary & operators, the type of that expression is converted ("decays") to a pointer type (char *), and the value of the expression is the address of the first element of the array. Therefore, the expression a has the same type and value as the expression &a[0] (and by extension, the expression *a has the same type and value as the expression a[0]).

C was derived from an earlier language called B, and in B a was a separate pointer object from the array elements a[0], a[1], etc. Ritchie wanted to keep B's array semantics, but he didn't want to mess with storing the separate pointer object. So he got rid of it. Instead, the compiler will convert array expressions to pointer expressions during translation as necessary.

Remember that I said arrays don't store any metadata about their size. As soon as that array expression "decays" to a pointer, all you have is a pointer to a single element. That element may be the first of a sequence of elements, or it may be a single object. There's no way to know based on the pointer itself.

When you pass an array expression to a function, all the function receives is a pointer to the first element - it has no idea how big the array is (this is why the gets function was such a menace and was eventually removed from the library). For the function to know how many elements the array has, you must either use a sentinel value (such as the 0 terminator in C strings) or you must pass the number of elements as a separate parameter.


  1. Which *may* affect how the address value is interpreted - depends on the machine.

An array declared like this

int a[10];

allocates memory for 10 ints. You can't modify a but you can do pointer arithmetic with a.

A pointer like this allocates memory for just the pointer p:

int *p;

It doesn't allocate any ints. You can modify it:

p = a;

and use array subscripts as you can with a:

p[2] = 5;
a[2] = 5;    // same
*(p+2) = 5;  // same effect
*(a+2) = 5;  // same effect

The array name by itself yields a memory location, so you can treat the array name like a pointer:

int a[7];

a[0] = 1976;
a[1] = 1984;

printf("memory location of a: %p", a);

printf("value at memory location %p is %d", a, *a);

And other nifty stuff you can do to pointer (e.g. adding/substracting an offset), you can also do to an array:

printf("value at memory location %p is %d", a + 1, *(a + 1));

Language-wise, if C didn't expose the array as just some sort of "pointer"(pedantically it's just a memory location. It cannot point to arbitrary location in memory, nor can be controlled by the programmer). We always need to code this:

printf("value at memory location %p is %d", &a[1], a[1]);

I think this example sheds some light on the issue:

#include <stdio.h>
int main()
{
        int a[3] = {9, 10, 11};
        int **b = &a;

        printf("a == &a: %d\n", a == b);
        return 0;
}

It compiles fine (with 2 warnings) in gcc 4.9.2, and prints the following:

a == &a: 1

oops :-)

So, the conclusion is no, the array is not a pointer, it is not stored in memory (not even read-only one) as a pointer, even though it looks like it is, since you can obtain its address with the & operator. But - oops - that operator does not work :-)), either way, you've been warned:

p.c: In function ‘main’:
pp.c:6:12: warning: initialization from incompatible pointer type
  int **b = &a;
            ^
p.c:8:28: warning: comparison of distinct pointer types lacks a cast
  printf("a == &a: %d\n", a == b);

C++ refuses any such attempts with errors in compile-time.

Edit:

This is what I meant to demonstrate:

#include <stdio.h>
int main()
{
    int a[3] = {9, 10, 11};
    void *c = a;

    void *b = &a;
    void *d = &c;

    printf("a == &a: %d\n", a == b);
    printf("c == &c: %d\n", c == d);
    return 0;
}

Even though c and a "point" to the same memory, you can obtain address of the c pointer, but you cannot obtain the address of the a pointer.


The array name behaves like a pointer and points to the first element of the array. Example:

int a[]={1,2,3};
printf("%p\n",a);     //result is similar to 0x7fff6fe40bc0
printf("%p\n",&a[0]); //result is similar to 0x7fff6fe40bc0

Both the print statements will give exactly same output for a machine. In my system it gave:

0x7fff6fe40bc0

An array is a collection of secuential and contiguous elements in memory. In C an array's name is the index to the first element, and applying an offset you can access the rest of elements. An "index to the first element" is indeed a pointer to a memory direction.

The difference with pointer variables is that you cannot change the location the array's name is pointing to, so is similar to a const pointer (it's similar, not the same. See Mark's comment). But also that you don't need to dereference the array name to get the value if you use pointer aritmetic:

char array = "hello wordl";
char* ptr = array;

char c = array[2]; //array[2] holds the character 'l'
char *c1 = ptr[2]; //ptr[2] holds a memory direction that holds the character 'l'

So the answer is kinda 'yes'.


Array name is the address of 1st element of an array. So yes array name is a const pointer.

참고URL : https://stackoverflow.com/questions/1641957/is-an-array-name-a-pointer

반응형