c++ c pointers

¿Por qué int*ptr_arr_int={1,2}; no funciona en C/C++?



pointers (7)

¿Por qué int* ptr_arr_int = {1,2}; da un error de compilación, pero mientras que char* ptr_arr_char = "amruth"; compila bien?

int* ptr_arr_int = {1,2}; // ->ERROR char* ptr_arr_char = "amruth"; // ->OK


Como se dijo, la cadena es una matriz de caracteres const char[7] y mientras que puede decaer a un char* , {1, 2} no puede decaer a int* (es una lista de inicializador de llaves, de manera similar: std::initializer_list ). Pero tenga en cuenta que también existe la declaración array [] que le permite declarar arrays automáticamente. Combine eso con la list-initialization desde C ++ 11 y podrá inicializar ambos a través de [] :

int ptr_arr_int[] = { 1,2 }; //OK char ptr_arr_char[] = "amruth"; //OK


Es simplemente porque la sintaxis del lenguaje lo dice. Respecto a las matrices:

  • Debemos inicializar una matriz con una lista cerrada con correas {...} , que no contenga más elementos de lo que cabrá dentro de la matriz.
  • Como regla especial, los arrays de caracteres pueden inicializarse con una cadena literal, "..." .

Sin embargo, no tiene matrices en su código, solo tiene punteros.

Un char* siempre se puede configurar para que apunte a un literal de cadena (en C), por lo que char* ptr_arr_char = "amruth"; es válida. Sin embargo, es un estilo a pescado, porque la cadena literal no se puede modificar. El estilo correcto es usar const char* .

C ++ es más estricto y los literales de cadena en C ++ tienen el tipo const char[] . y es probable que un compilador de C ++ dé una advertencia a lo largo de las líneas de "conversión en desuso" si no usa const char* .

En cuanto a int* ptr_arr_int = {1,2}; , tiene dos problemas.

  • {1,2} es una lista de inicialización, pero ptr_arr_int es un solo elemento, por lo que no tiene ningún sentido. Existe una regla especial e impar que realmente nos permite usar {} al inicializar una sola variable, pero entonces solo debe tener un inicializador único dentro.
  • No puede inicializar un puntero con un entero. Consulte "Problemas con el puntero desde entero / entero desde un puntero sin conversión" .

Si pretendía que el puntero apunte a una matriz temporal, que solo existe en el ámbito local, entonces podría haber usado la característica de C llamada literal compuesto :

int* ptr_arr_int = (int[]){1,2};

Sin embargo, esto no es posible hacer AFAIK en C ++, a menos que confíe en extensiones no estándar. Pero en cualquiera de los dos idiomas, por supuesto, puedes hacer esto:

int arr[2] = {1,2}; int* ptr_arr_int = arr;


Está declarando una matriz de punteros a int ( int* ). Pero los valores con los que inicializa la matriz ( 1 y 2 ) no son punteros a enteros, son int simples.


No ... eso no es correcto ... ese inicializador solo es válido para matrices. Te habia escrito

int array[] = {1, 2};

sería válido ... pero está intentando inicializar una variable de puntero , por lo que sería válido (a pesar de la advertencia, porque 0xf45 no es una dirección):

int *pointer = { 0xf45 };

(porque solo se coloca una entrada y se considera un solo valor) pero:

int *pointer = { 0xf45, 0 };

(Recibirá otra advertencia sobre el excess elements in scalar initializer ) Esto significa que para una sola variable intentó usar dos inicializadores. La notación de llaves nació para poder inicializar matrices, pero también se permite su uso con tipos escalares. Esto significa que las dos notaciones:

{ 0 }; /* a single value between braces */

y

0;

son equivalentes

La solución a su problema es hacer un paso adicional, declarar una matriz y luego señalarla desde el puntero:

int array[] = {1, 2}; int *pointer = array;

pero piense que puede hacer que el puntero apunte a un lugar diferente al principio de la matriz, y no puede hacer que la matriz se mueva mágicamente a otro lugar. Y &array significa la dirección de array array mientras que &pointer significa la dirección del puntero variable de pointer . pointer apunta a la dirección de la array , pero la array es un puntero constante que apunta a la dirección de la array[0] .

Los punteros y las matrices son algo confusos, pero nunca pienses que son lo mismo. Simplemente compara sizeof(char[120]) con sizeof(char *) y verás.


No puedes, porque int * no es una estructura que pueda inicializarse con dos valores como hiciste con = {1,2}; .

Podrías haberlo inicializado de esta manera:

int * ptr_arr_int = nullptr;

La otra forma podría haber sido usar un objeto que espera dos valores para la construcción:

struct Point { int a; int b; };

entonces podrías haber escrito:

Point p = {1,2};


Una cadena por sí misma ya implica una clase de almacenamiento: es una matriz de caracteres static (+ efectivamente const ) declarada con una sintaxis especial.

En contraste con eso, no está claro cómo se debe almacenar {1, 2} en int *ptr_arr_int = {1, 2} . ¿Debería ser static o auto ?

Si desea que sea auto cuando esté en un ámbito local o static en el ámbito de archivo, entonces en C> = 99 puede hacer explícitamente int *ptr_arr_int = &(int[]){1,2}[0]; (El &[0] es opcional).

Posiblemente podrías hacer esto implícito, pero ¿hasta dónde llevarías esto? int ****x = {1,2}; La inicialización mediante la creación de una matriz, un puntero a ella, un puntero a eso, etc., podría dar como resultado un poco de código / datos y esconder una gran cantidad de código / datos en una construcción simple no es del todo la manera C. Tampoco estaría claro cuándo la sintaxis del corchete debería estar inicializando el tipo básico de destino final o algunos de los punteros intermedios.


"amruth" es un tipo const char[7] en C ++, y un tipo char[7] en C (aunque el comportamiento al intentar modificar la cadena no está definido).

Esto puede decaer a un tipo const char* o char* respectivamente en algunas circunstancias, como la suya.

Aunque un int[2] se deteriorará de manera similar a un int* en algunas circunstancias, {1, 2} no es ni un int[2] ni un tipo const int[2] ; más bien es un inicializador de llaves .