¿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, peroptr_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
.