c++ - que - punteros y arreglos en c
Obtener un puntero colgante al devolver un puntero desde una matriz de estilo C local (2)
La matriz arr
tiene duración de almacenamiento local y desaparecerá al final del alcance. Sin embargo, la "test"
literal de cadena es un puntero a una ubicación de almacenamiento estática. El almacenamiento temporal de este puntero en la matriz local arr
antes de devolverlo no cambia eso. Siempre será una ubicación de almacenamiento estática.
Tenga en cuenta que si la función fuera a devolver un tipo de cadena de estilo C ++ en lugar de un estilo C const char *
, la conversión / contabilidad adicional probablemente le deje un valor limitado en el tiempo de vida según las reglas temporales de C ++.
Estoy un poco confundido por el siguiente código:
#include <iostream>
const char* f()
{
const char* arr[]={"test"};
return arr[0];
}
int main()
{
auto x = f();
std::cout << x;
}
En mi opinión, este código debe ser UB (comportamiento indefinido). Devolvemos un puntero a un elemento de matriz estilo C dentro de un ámbito local. Las cosas deberían salir mal. Sin embargo, ninguno de los compiladores con los que probé se quejó (utilicé -Wall -Wextra -pedantic
en ambos g ++ y clang). valgrind
tampoco se queja.
¿El código anterior es válido o es UB como uno pensaría?
PD: ejecutarlo parece producir el resultado "correcto", es decir, mostrar "prueba", pero eso no es una indicación de corrección.
No, no es UB.
Esta:
const char* f()
{
const char* arr[]={"test"};
return arr[0];
}
Se puede reescribir al equivalente:
const char* f()
{
const char* arr0 = "test";
return arr0;
}
Así que solo estamos devolviendo un puntero local, a un literal de cadena. Los literales de cadena tienen una duración de almacenamiento estática , nada cuelga. La función es realmente la misma que:
const char* f()
{
return "test";
}
Si hiciste algo como esto :
const char* f() {
const char arr[] = "test"; // local array of char, not array of char const*
return arr;
}
Ahora que es UB, estamos devolviendo un puntero colgante.