c++ - que - puntero a char vs puntero a matrices
punteros en c (4)
¿Por qué puedo imprimir
h
y tenerbonjour
como salida y no puedo hacer lo mismo conp
? también parece que cuando incrementeh++
e imprima nuevamente, me pongo enonjour
. ¿En qué se diferencian los punteros conchar
?
La biblioteca estándar proporciona dos sobrecargas de la función operator<<
del operator<<
para manejar punteros.
Una sobrecarga de función miembro:
basic_ostream& operator<<( const void* value );
y una sobrecarga de función no miembro:
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
El primero se invoca cuando cout << ptr
se usa para todos los punteros que no son de tipo char*
o char const*
. El segundo se usa para todos los punteros que son de tpe char*
o char const*
. El segundo saca todo hasta los caracteres nulos de terminación, mientras que el primero emite solo el valor del puntero.
Eso explica la salida.
Es instructivo entender por qué la biblioteca estándar los trata de manera diferente.
El lenguaje y las bibliotecas estándar hacen excepciones a las cadenas terminadas nulas que están representadas por char*
y char const*
. Cuando se trata de cadenas, el carácter nulo ( ''/0''
) actúa como un valor centinela que marca el final de la cadena. No hay tal valor para otros tipos. Por lo tanto, un int*
no puede tratarse igual que un char*
.
Pensé que tenía un conocimiento decente de los indicadores hasta que decidí revisar algunos de los llamados ejemplos triviales.
Una cosa que sé es que al declarar una matriz, diga:
int arr[2] {3, 5};
arr
mantendrá el valor del primer elemento en la matriz, así que intentar imprimir eso ( cout << arr
) da obviamente la dirección de arr[0]
. Incluso aunque mi programa use punteros, sigue siendo similar.
Mi pregunta es por qué puedo imprimir h
y tener bonjour
como salida, pero no puedo hacer lo mismo con p
?
También parece que cuando incremente h++
e imprima nuevamente, me pongo en onjour
. ¿En qué se diferencian los punteros con char
?
#include <iostream>
#include <string>
int main()
{
char* h = "bonjour";
int k[4]{3, 4, 5, 6};
int * p = k;
std::cout << "Hello, "<< h << "!/n";
}
Creo que esto tiene que ver con el operator <<
para char*
e int*
más que cualquier otra cosa. Los programadores C se utilizan para anular la impresión de cadenas terminadas, por lo que se creó un método para imprimirlas. int
s se puede imprimir directamente. Un char
no podrá imprimir una cadena completa.
Cuando transmites h
, estás usando esta sobrecarga :
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
Pero cuando transmites p
, estás usando este :
basic_ostream& operator<<( const void* value );
El primero imprimirá cada byte hasta que llegue a un /0
, este último simplemente imprimirá la dirección. Es decir, simplemente hay un caso especial para const char*
que se está aprovechando.
char*
puede ser especial en algunas circunstancias, porque C decidió usarlo para representar cadenas. En ese caso, un char*
refiere a una matriz de caracteres terminada nula, también conocida como C-string. La razón por la que puede imprimir h
pero no p
es porque existe una función que tiene un manejo especial para char*
:
std::ostream::operator<<(std::ostream& os, const char*);
Puede proporcionar su propia sobrecarga para imprimir matrices de enteros terminados nulos:
std::ostream& operator<<(std::ostream& os, const int* arr) {
while (int i = *arr++) {
os << i;
if (*arr) os << ", ";
}
return os;
}
int main()
{
const int arr[] = {1, 2 ,3, 4, 0};
std::cout << arr << "/n";
}
Sin embargo, esto es extremadamente peligroso porque la mayoría de las matrices de enteros no terminan con un cero y no todos los punteros a enteros son matrices.