¿Cuál es la diferencia entre _tmain () y main () en C ++?

Si ejecuto mi aplicación C ++ con el siguiente método main () todo está bien:

int main(int argc, char *argv[]) { cout << "There are " << argc << " arguments:" << endl; // Loop through each argument and print its number and value for (int i=0; i<argc; i++) cout << i << " " << argv[i] << endl; return 0; } 

Obtengo lo que espero y mis argumentos se imprimen.

Sin embargo, si uso _tmain:

 int _tmain(int argc, char *argv[]) { cout << "There are " << argc << " arguments:" << endl; // Loop through each argument and print its number and value for (int i=0; i<argc; i++) cout << i << " " << argv[i] << endl; return 0; } 

Simplemente muestra el primer caracter de cada argumento.

¿Cuál es la diferencia que causa esto?

_tmain no existe en C ++. main hace.

_tmain es una extensión de Microsoft.

main es, según el estándar C ++, el punto de entrada del progtwig. Tiene una de estas dos firmas:

 int main(); int main(int argc, char* argv[]); 

Microsoft ha agregado un wmain que reemplaza la segunda firma con esto:

 int wmain(int argc, wchar_t* argv[]); 

Y luego, para facilitar el cambio entre Unicode (UTF-16) y su conjunto de caracteres multibyte, han definido _tmain que, si Unicode está habilitado, se comstack como wmain , y de lo contrario como main .

En cuanto a la segunda parte de su pregunta, la primera parte del rompecabezas es que su función principal es incorrecta. wmain debería tomar un argumento wchar_t , no char . Dado que el comstackdor no aplica esto para la función main , se obtiene un progtwig donde se pasa una matriz de cadenas wchar_t a la función main , que las interpreta como cadenas de caracteres.

Ahora, en UTF-16, el juego de caracteres utilizado por Windows cuando Unicode está habilitado, todos los caracteres ASCII se representan como el par de bytes \0 seguido del valor ASCII.

Y dado que la CPU x86 es little-endian, el orden de estos bytes se intercambia, de modo que el valor ASCII viene primero, seguido por un byte nulo.

Y en una cadena de caracteres, ¿cómo termina normalmente la cadena? Sí, por un byte nulo. Entonces, su progtwig ve un montón de cadenas, cada una de ellas de un byte de largo.

En general, tiene tres opciones al hacer la progtwigción de Windows:

  • Use explícitamente Unicode (call wmain, y para cada función de API de Windows que tome argumentos relacionados con char, llame a la versión -W de la función. En lugar de CreateWindow, llame a CreateWindowW). Y en lugar de usar char usa wchar_t , y así sucesivamente
  • Deshabilitar explícitamente Unicode. Llame a main, y CreateWindowA, y use char para cadenas.
  • Permitir ambos. (llame a _tmain y CreateWindow, que resuelven a main / _tmain y CreateWindowA / CreateWindowW), y use TCHAR en lugar de char / wchar_t.

Lo mismo se aplica a los tipos de cadena definidos por windows.h: LPCTSTR se resuelve en LPCSTR o LPCWSTR, y para cualquier otro tipo que incluya char o wchar_t, siempre existe una versión -T que puede usarse en su lugar.

Tenga en cuenta que todo esto es específico de Microsoft. TCHAR no es un tipo estándar de C ++, es una macro definida en windows.h. wmain y _tmain también están definidos solo por Microsoft.

_tmain es una macro que se redefine dependiendo de si comstack o no con Unicode o ASCII. Es una extensión de Microsoft y no se garantiza que funcione en ningún otro comstackdor.

La statement correcta es

  int _tmain(int argc, _TCHAR *argv[]) 

Si se define la macro UNICODE, eso se expande a

 int wmain(int argc, wchar_t *argv[]) 

De lo contrario, se expande a

 int main(int argc, char *argv[]) 

Su definición va un poco de cada uno, y (si tiene UNICODE definido) se expandirá a

  int wmain(int argc, char *argv[]) 

lo cual es simplemente incorrecto.

std :: cout funciona con caracteres ASCII. Necesita std :: wcout si usa caracteres anchos.

intenta algo como esto

 #include  #include  #if defined(UNICODE) #define _tcout std::wcout #else #define _tcout std::cout #endif int _tmain(int argc, _TCHAR *argv[]) { _tcout << _T("There are ") << argc << _T(" arguments:") << std::endl; // Loop through each argument and print its number and value for (int i=0; i 

O simplemente podría decidir de antemano si usar caracteres anchos o estrechos. 🙂

Actualizado el 12 de noviembre de 2013:

Cambió el tradicional "TCHAR" a "_TCHAR", que parece ser la última moda. Ambos funcionan bien.

Fin de actualización

la convención _T se usa para indicar que el progtwig debe usar el juego de caracteres definido para la aplicación (Unicode, ASCII, MBCS, etc.). Puede rodear sus cadenas con _T () para tenerlas almacenadas en el formato correcto.

  cout << _T( "There are " ) << argc << _T( " arguments:" ) << endl; 

Bueno, la pregunta parece haber sido respondida bastante bien, la sobrecarga de UNICODE debería tomar una matriz de caracteres amplia como su segundo parámetro. Entonces, si el parámetro de la línea de comando es "Hello" , probablemente terminaría como "H\0e\0l\0l\0o\0\0\0" y su progtwig solo imprimiría la 'H' antes de que vea lo que cree que es un terminador nulo

Entonces ahora puede preguntarse por qué incluso comstack y enlaces.

Bueno, se comstack porque puede definir una sobrecarga para una función.

La vinculación es un problema un poco más complejo. En C, no hay información de símbolo decorada por lo que solo encuentra una función llamada main. El argc y el argv probablemente siempre estén allí como parámetros de la stack de llamadas, por si acaso, incluso si su función está definida con esa firma, incluso si su función pasa a ignorarlos.

A pesar de que C ++ sí tiene símbolos decorados, es casi seguro que usa enlaces C para main, en lugar de un enlazador inteligente que busca cada uno por turno. Así que encontró su wmain y puso los parámetros en la stack de llamadas en caso de que sea la int wmain(int, wchar_t*[]) .

Con un pequeño esfuerzo de templatar esto, funcionará con cualquier lista de objetos.

 #include  #include  #include  char non_repeating_char(std::string str){ while(str.size() >= 2){ std::vector rmlist; for(size_t i = 1; i < str.size(); i++){ if(str[0] == str[i]) { rmlist.push_back(i); } } if(rmlist.size()){ size_t s = 0; // Need for terator position adjustment str.erase(str.begin() + 0); ++s; for (size_t j : rmlist){ str.erase(str.begin() + (js)); ++s; } continue; } return str[0]; } if(str.size() == 1) return str[0]; else return -1; } int main(int argc, char ** args) { std::string test = "FabaccdbefafFG"; test = args[1]; char non_repeating = non_repeating_char(test); Std::cout << non_repeating << '\n'; }