Arrays are pointers, right?

Asked

Viewed 2,425 times

45

After all, in C, an array a[] becomes a pointer *a? If not, what are arrays? What are the differences between them? How arrays work internally?

  • 1

    Good question, so you can have something canonical to use in other answers that do not fit to be explaining in detail.

6 answers

31


First, understand that we often make simplifications to give understanding to those who have not yet mastered the subject. As the person who is very lay evolves he can pay attention to the details. I won’t spend everyone here but I go a little beyond the simplification usually done in answers given to those who are learning and still can not talk at the same level of those who have learned everything from language.

Introducing

Arrays are not pointers. In the pmg response in another question has even a link where it shows this. Formally they are different types. In some cases it is possible to use one when expecting another. There is an automatic conversion, but not at all. There is semantic difference, besides the obvious difference in syntax for each one.

A array is a single, previously allocated portion of continuous element memory (all of the same type), fixed in size and location.

A pointer is a reference to any data (of a specific type) anywhere.

Internally they function as pointers. The computer does not understand arrays. This is an existing definition in higher-level languages. A lower-level mechanism is required to access memory data. This mechanism is the pointer. But the formal definition of terms and specific functioning in the language C indicates a difference between them.

The array may have information of its size known to the compiler. In this case it obviously cannot have its size changed. Pointer has no set size. There are arrays no size set at compile time that behave closer to the pointer.

The array in itself can not have its size changed, but, as it can be accessed as a pointer, nothing prevents to add information at the end of it (although it is not simple to do right and not safe to do this, in fact it will probably corrupt the memory) or access parts of the memory beyond it, as if it were part of it. The code must take care of this.

The location of array also cannot be changed by definition. If you need to change location, in the background you will be creating another array. The pointer can be changed and pointed to another location, as shown below. Evidently it will be pointing to another object, even if it has the same content.

Diferença array e ponteiro

A array has its value in the same storage location of the variable. A pointer indicates where the value of a possible value sequence, it points to the first element. Even the compiler knowing the size of the array it does not help to check if access is being done outside of the band of it, the programmer is responsible for handling it. The compiler prevents a array of zero elements, after all it can not point to anything, it has to point to at least the element 0. If it will have a useful value there is another problem.

The size of a array is the size of its allocation. The size of a pointer is the size of its type. To know the amount of elements of a array we should make an account by dividing the size of the array by the size of his type.

They are interchangeable?

The point is that to access a array or a specific element of it is possible to use a pointer. After all the array is somewhere in memory and somewhere in memory can always be accessed by a pointer. I won’t go into the details of virtual memory and access protection, it’s not the case now.

So the form of access is interchangeable. In fact when you do array[index] is making *(array + index) (recalling that the value of index is multiplied by sizeof of the kind of array). Therefore there are cases where the decay of array pointer. Obviously it is possible to access a chunk of memory whose location is known as if it were a array, even though it’s not.

That’s why array[index] is the same as index[array], although it is strange to write like this. The order of the sum does not change the result.

There are several cases where you try to use one in place of another gives error. It is not the whim of the compiler, it will actually have problems running the operation correctly. When you use a reference to a array, the pointer can be used in place.

No difference/advantage to use char array[] (note that there is no set size) or char *array unless the first clearly indicates that it is a array. It is information that serves the programmer.

Note that if you pass one array for a function, the passage will be made as if it were a reference. Because in the background is passed a pointer. So the passage is by value, but the value is a pointer to where the array and not the array in itself. This is one of the things that creates confusion between array and pointer. This occurs even when using the syntax of array ([]), after all they are identical, but in the background is using a pointer.

char array[] = "Hello world";

"Hello world" is a array 12-inch (you know why it’s 12 and not 11, right?). It will be allocated to memory (probably a static area of memory and the variable array will point to the address of your location. Understand why we speak informally that the array is a pointer? He’s not the type pointer, he just points to something.

Array there is no?

Language to manipulate lacks facilities arrays. Everything works as if they were pointers, you have to take care of everything. Then we talked informally that in the background array does not exist in C. Just as string does not exist either. Although there is a type array, the language does not treat it in a special way. Remembering that string is just a sequence of char. They can be allocated in a array or pointer. And obviously can be interchanged in some situations.

Completion

Technically they are different types with internal mechanisms that work the same way and in some situations can be exchanged.

Understand that the pointer is much more flexible and a more generic mechanism.

Details can be found on link at the beginning of the reply.

14

An array is associated with a memory space capable of supporting N array base type elements.

A pointer is associated with a memory space capable of pointing to another memory space.

The large difference between pointer and array can be seen in the result of sizeof

int value = 0;
int *ptr = &value;
int array[42] = {0};

printf("sizeof ptr = %d\n" (int)sizeof ptr);
printf("sizeof arr = %d\n" (int)sizeof arr);

The problem with managing arrays and pointers is that in many uses made with arrays these are converted (internally by the compiler) into a pointer to its first element (in the case of sizeof this conversion is not applied), losing with this conversion the information of how many elements make up the array.

For the same reason, another problem is the passage of parameters between functions when they include one (or more) array. The array is converted to a pointer to the first element and it is this pointer that is passed (no information about the size of the array).

Another reason to confuse the two language elements is that a pointer can be used with the same array syntax.

int array[42] = {42};
int *ptr = a;

In the above code the array variable has space for 42 type values int. The variable ptr points to the first of these values (for a[0]);

To put a specific value on, for example a[10] you can use the array or pointer with equal syntax

a[10] = 1000;
p[10] = 1000;

although the basic "philosophy" is different (direct access versus relative access).


Imagine an array like a train and a pointer like a person pointing to the first carriage.

4

Being short and thick... Yes, a vector is a pointer, although the opposite is not always true.

First let’s get to the definitions:

  • A pointer stores a memory address. On a 32-bit architecture, an address has 32 bits and corresponds to int type. This has a very cool effect: if you have any pointer and increment it, it now points to the next memory space.

  • Vectors are syntactic sugar to perform two tasks: reserve a memory space to store information, and access this information with a simpler syntax.

So note that the following two codes achieve the same goal:

int vetor[10] = { 0 };
// Em C, isso gera um array com dez elementos de valor zero

for (int i = 0; i < 10; i++) {
    vetor[i] = i;
    printf("%d", vetor[i]);
}

In that case, it shall be printed: 0123456789 and the vector will contain, in order, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

Now with pointers:

int *ptr = malloc(10 * sizeof *ptr);
for (int i = 0; i < 10; i++) {
    *(ptr + 1) = i;
    printf("%d", *(ptr + i));
}

The printed result will be the same, and we will have in memory ten integers in consecutive positions, in the following order: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

If you have noticed correctly, you have seen that both one code and the other have done exactly the same thing. But the first is simpler and more familiar to those who have worked with other higher-level languages such as Java, C# or Javascript (although the vector is somewhat different in the latter).

As they are the same thing, you can mix the two forms with impunity :D See:

int *ptr = malloc(10 * sizeof *ptr);
for (int i = 0; i < 10; i++) {
    ptr[i] = i;
    printf("%d", *(ptr + i));
}

And

int vetor[10] = { 0 };
int *ptr = &vetor[0];

for (int i = 0; i < 10; i++) {
    vetor[i] = i;
    printf("%d", *(ptr + i));
}

I hope I have answered the question in practice.

2

Complementing the responses of the companions above. An array as such is a "variety" of elements of the same type within a given space in memory. High-level languages abstract this space with "index’s".

From an index referenced to a position that consecutively points to an address, it is possible to access, read or enter data on the indicated position:

#include <iostream>
#define SIZE 8
using namespace std;

int main() {
     int numeros[SIZE]; 
     numeros[0] = 1; // inserindo dados num array a partir de um index
     cout << numeros[0]; // lendo dados de um array a partir do index desejado
}

The index is a simple way to access a value from an array. Pointers do this work in a complex way, here’s an example:

#include <iostream>
#define SIZE 8
using namespace std;

int numeros[SIZE]; // não se esqueça que todo array, de qualquer tipo inicia com posição 0

void AtribuirValor(); // protótipo da função

int main()
{
    AtribuirValor();
    int *ptr = numeros; // ponteiro para um array de 8 posições criado na stack referenciando ao array numeros

    for (int i = 0; i < SIZE; i++)
    {
        cout << "index: " << i << ", endereco: " << &ptr[i] << ", valor:" << ptr[i] << endl; // acessando os valores, index's e endereços do array numeros a partir de um ponteiro para inteiros 
    }

    cout << "\nComprovando... \n\n";

    for (int c = 0; c < SIZE; c++) 
    {
        cout << "index: " << c << ", endereco: " << &numeros[c] << ", valor: " << numeros[c] << endl; // acessando os valores, index's e endereços do array numeros
    }
}

void AtribuirValor()
{
    for (int j = 0; j < SIZE; j++) 
    {
        numeros[j] = 10+j; // atribuindo valores para dentro do array 
    }
}


/*
OUTPUT: 
index: 0, endereco: 0x408020, valor:10
index: 1, endereco: 0x408024, valor:11
index: 2, endereco: 0x408028, valor:12
index: 3, endereco: 0x40802c, valor:13
index: 4, endereco: 0x408030, valor:14
index: 5, endereco: 0x408034, valor:15
index: 6, endereco: 0x408038, valor:16
index: 7, endereco: 0x40803c, valor:17 

Comprovando...

index: 0, endereco: 0x408020, valor: 10
index: 1, endereco: 0x408024, valor: 11
index: 2, endereco: 0x408028, valor: 12
index: 3, endereco: 0x40802c, valor: 13
index: 4, endereco: 0x408030, valor: 14
index: 5, endereco: 0x408034, valor: 15
index: 6, endereco: 0x408038, valor: 16
index: 7, endereco: 0x40803c, valor: 17
*/

For those interested, here is the main function disassemble for x64 architecture - Windows 10:

   Dump of assembler code for function main:

   0x00401410 <+0>:     lea    0x4(%esp),%ecx
   0x00401414 <+4>:     and    $0xfffffff0,%esp
   0x00401417 <+7>:     pushl  -0x4(%ecx)
   0x0040141a <+10>:    push   %ebp
   0x0040141b <+11>:    mov    %esp,%ebp
   0x0040141d <+13>:    push   %ecx
=> 0x0040141e <+14>:    sub    $0x24,%esp
   0x00401421 <+17>:    call   0x401bc0 <__main>
   0x00401426 <+22>:    call   0x4015a3 <_Z13AtribuirValorv>
   0x0040142b <+27>:    movl   $0x408020,-0x14(%ebp)
   0x00401432 <+34>:    movl   $0x0,-0xc(%ebp)
   0x00401439 <+41>:    cmpl   $0x7,-0xc(%ebp)
   0x0040143d <+45>:    jg     0x4014df <_fu0___ZSt4cout+145>
   0x00401443 <+51>:    movl   $0x406045,0x4(%esp)
   0x0040144b <+59>:    movl   $0x6ff44aa0,(%esp)

-2

arrays and pointers are completely different things. the cat jump is that when the compiler needs to access an element of the array the compiler treats the multidimensional array as if it were a pointer. a constant pointer, that is a pointer whose content , which is a memory address, does not change. this pointer points to a region of memory.This discussion is not for beginners, since it is how the compiler treats an array under the tanneries. when you need to work with an array, the compiler treats the array as if it were a pointer. what happens when a compiler needs to access an array! as if it controe an array ? using a constant pointer.

How subscript works in a multidimensional array in the c language or how I imagine a multidimensional array works in gcc or the strange connection between array, pointer, operator skips and subscript operator.

                       1 4 5                               
int meu_array[2][3]=   
                       3 7 8

An array has the identifier meu_array and 2 dimensions with 6 int elements . the identifier meu_array is handled by the compiler in two ways:

first way. is treated as if it were an array of 2 dimensions and 6 elements Example:
sizeof (meu_array);

second way . the identifier meu_array is treated as a pointer pointing to a one-dimensional array of 3 elements int {1,4,5}. this pointer has an offset of 3 int elements if incremented this pointer points to a new one-dimensional array of 3 int elements the new pointed array is {3,7,8}.

A multidimensional array with n dimensions is treated by the compiler as if it were a pointer pointing to a dimensional array with n-1 dimensions.

This even discards a dimension, loses information in this process.This process is called array decay to a pointer (array Decay).

Examples:

  • int array1[4][5][6] compiler interprets array1 as if it was a pointer given by the following expression int (*point1)[5][6] .
  • int array2 [2][3] compiler interprets array2 as if it was a pointer given by the following expression int (*point2)[3] .
  • Float array3[6] compiler interprets array3 as if it was a pointer given by the following expression float (*point3).

Note taking the case of array1. This is a multidimensional array of 4x5x6=120 int elements, but pointer1 points to a multidimensional array of 5x6=30 int elements.

Note taking the case of array2. This is a multidimensional array of 2x3=6 int elements,but pointer2 points to a multidimensional array of 3 int elements.

Note taking the case of array3. This is a one-dimensional array of 6 elements but the pointer3 points to a float element.

Note the offset. Pointer1 has an offset of 5*6=30 int. Pointer2 has an offset of 3 int . Pointer3 has an offset of 1 float.

Passing a multidimensional array as a function argument

datum: float array[2][3] the statement void função_recebe_array(float array_parametro[2][3]) is equivalent void função_recebe_array( float (*ponteiro_parametro)[3]) so should pass the value of the dimension: void função_recebe_array( int linhas ,float (*ponteiro_parametro)[3])

What it means to direct a pointer pointing to an array ?

The result of dereferencing a pointer that points to an int is an int value . In the case of a pointer pointing to an array the result is an array. But as this array is a pointer . In practice dereferencing a pointer pointing to an array results in a pointer pointing to a new array with n-1 dimension.

Subscript operator and dereferencia operator

when writing ,array[i][j][k] compiler interprets it as *(*(*( array+i)+j)+k). You guess the result of the expression array[0][0][0] ? It is the first value of the array when you use subscript you are using pointer reference that points to an array.

#include <stdio.h>

int main (void)
{
int matriz_2x3x4[2][3][4]={7,4,3,2,115,100,20,30,50,60,70,80,90,93,95,83,55,52,36,27,25,21,20,5};

printf("\no endereço de matriz_2x3x4 é %p \n",&matriz_2x3x4[0][0][0]);
printf("\no valor  de matriz_2x3x4[1][2][3] é %i \n",matriz_2x3x4[1][2][3]);
printf("\no valor  de matriz_2x3x4[1][2][3]  é %i \n",*(*(*(matriz_2x3x4+1)+2)+3));

int  (*ponteiro_matrix_3x4)[3][4]=matriz_2x3x4;
printf("\n o ponteiro_matrix_3x4 aponta para   %p \n",matriz_2x3x4);
int  (*ponteiro_array_4)[4]=*(matriz_2x3x4+1);
printf("\n o ponteiro_array_4 aponta para   %p \n",ponteiro_array_4);
printf("\n a segunda matrix_3x4 aponta para   %p \n",&(matriz_2x3x4[1][0][0]));
int  (*ponteiro_int)=*(ponteiro_array_4+2);
printf("\n o ponteiro_array_4 aponta para o endereço  %p \n",ponteiro_array_4);
printf("\n o valor 90 esta no endereço   %p \n",&(matriz_2x3x4[1][0][0]) );

printf("\n o ponteiro_array_4 +2 aponta para o endereço  %p \n",ponteiro_array_4+2);
printf("\n o valor 25 esta no endereço   %p \n",&(matriz_2x3x4[1][2][0]) );

                 
int  elemento_1_2_3_da_matriz=*(ponteiro_int+3);
printf("\n o elemento matriz_2x3x4[1][2][3] e   %i \n",elemento_1_2_3_da_matriz);

return 0;
}

inserir a descrição da imagem aqui

bibliography : https://riptutorial.com/c/example/13402/misunderstanding-array-decay

  • You confused the abstraction with the array implementation and put it together into one thing. Array is just a pointer to a memory placeholder. How one moves within this reserved space of memory is abstraction.

  • 1

    Your answer is meaningless

-4

If you have an array with 'n' positions, it is a pointer when you put only its nomenclature, that is, you do not index it, this way:

int array[10];
array[0... 9]; <-- Quando você colocar uma posição específica ele se torna uma estância de uma variável, porém se colocado da forma abaixo:   

array;  <-- este se trata de um ponteiro que aponta para estas 10 posições na memória.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.