Fix (not matrix) with double pointer in C ++

2

I do not understand how to handle an array with a double pointer (it's not a matrix, it's a linear array). I did some tests with the following code:

 int *num = new int;

 int** algo = #//acá se pasa por referencia (no por copia), el puntero apuntará a la dirección de num
 int k = 6;
 int p = 5;

 algo[7] = &k; //el arreglo en esa posición (que no inicialicé ¿?) toma la dirección de k
 algo[500] = &p;

 cout << *algo[500]; //se imprime los valores de esos arrays en esas posiciónes, que nunca inicialicé
 cout << *algo[7];

The code works and although I did it, I do not understand it well, since until now I fixed the arrays to a fixed size and when I initialize them, the following questions arise:

  • Did it really get initialized?
  • Is this well thought out or can it give problems?
  • How can I know the size of the array?

This is part of an exercise that they sent me to do in the faculty.

    
asked by Mathias 23.03.2018 в 03:26
source

2 answers

3

You are right in everything you say and in all your comments.

int *num = new int;

That, certainly, creates a int . Neither more nor less than 1 and only 1 int .

So, the big question is ... why does it work?

This is going to extend a bit. Let's see if with an image ( taken from here ) ...

Each time you make function calls, the arguments are placed on the stack ( stack ). You have it at the top of the image.

The data created with new is occupying memory in the zone marked heap .

But all of it , from the part marked as .text to the last byte of stack belongs to your program . The system controls certain things, such as writings in read-only zones. But, for the rest, it's yours .

That means that, in fact, you can read and write in all your memory; another thing is that what you find have correct values.

The mechanism of dynamic memory reserve what it does is to organize some internal structures, so that you do not trample your own data; it guarantees that you will use different memory addresses for different things.

Initialization, on the other hand, is the mechanism by which you assign known initial values to variables.

But all of that are extra things , facilities we get from the system, from libraries, ... access to raw memory, skipping any logical organization > our , is always allowed.

That's why your code works. You read and write in your memory ; that you trample code structures (yours or from libraries), that you read initialized values or not ... that's the programmer's problem.

That is the great advantage and the big problem of C and C ++. They allow you to use completely the memory of your process. You can optimize your code, if necessary, for specific situations, skipping the functions of the libraries to manage the memory as you want.

And, for that matter, if you're not careful, you can corrupt the memory, write values where you should not, or read things that have not been written correctly.

But, in general, accessing random memory locations INSIDE your program is not an error in itself; in fact, it is perfectly valid (your code proves it).

Another thing very different is that we know what we are doing ...

    
answered by 23.03.2018 / 06:17
source
5

Formations in C ++.

Both C and C ++ 1 do not perform limit checks on the 2 formations, in the case of C and C ++ 1 they are not made these checks to favor the performance of the code.

In C ++ there is the formation data type, which imbues the size of the formation in the type, but only if that size is known at compile time.

using cien_int = int[100];

cien_int a; // Tanto 'a' como 'b' tienen el mismo tipo...
int b[100]; // ... el tipo es 'formación de 100 int'.

But the formation of decays in pointer to the underlying type of training when used in various contexts, for example:

template <typename T>
void f(T) { ... }

using cien_int = int[100];

cien_int a; // Tanto 'a' como 'b' tienen el mismo tipo...
int b[100]; // ... el tipo es 'formación de 100 int'.

f(a);
f(b);

In the previous code, in both cases the type T of the template function f is deducted as int * instead of int[100] . This is important because it shows us that we can receive a pointer to a training with reserved memory but having lost information about the size associated with the training.

Once the concepts have been introduced, we will address the questions.

  

Was it really initialized?

All these instructions are initializations:

int *num = new int; // Reserva un 'int' en memoria dinámica y lo almacena en 'num'.
int** algo = &num;  // Almacena la dirección de meoria de 'num' en 'algo'.
int k = 6;          // Almacena 6 en 'k'.
int p = 5;          // Almacena 5 en 'p'.

These lines are not initializations, they are assignments:

algo[7] = &k;   // Asigna la dirección de memoria de 'k' en la octava posición de 'algo'.
algo[500] = &p; // Asigna la dirección de memoria de 'p' en la quingentésima primera posición de 'algo'

The problem with the previous assignments is that they access memory that does not belong to the program:

Since no limit checks are made, it is possible to access and write in those memory zones, even if they have not been assigned to our program. This could lead to a access violation , or erratic behavior of the 3 program. sup>.

  

Is this well thought out or can it give problems?

It is difficult to know if it is well thought out with the little code that you share, but undoubtedly, as it has been commented in the previous point, it can give problems ... serious problems.

  

How can I know the size of the arrangement?

You can not. Pointers do not store size information; but you have alternatives:

  • End Mark : You can reserve an additional position where you would save a value that marks the end of the data collection.

    int **algo = new int*[501];
    algo[500] = 0xf10a1;
    
  • Additional variable : At the time of memory reservation, saving the size in an additional variable.

    int tamanyo = 500;
    int **algo = new int*[tamanyo];
    
  • stl : Using a container from the standard template library you can have control over size and memory management, read this thread to find out which one suits your needs.
  • And other languages.
  • Also known as arrays (or in English arrays).
  • For example, the invocation of infraseres of the ninth sphere of hell, which would be fired by your nostrils .
  • answered by 23.03.2018 в 10:31