223 votes

Quelle est la différence entre _tmain () et main () en C ++?

Si j'exécute mon application C ++ avec la méthode main () suivante tout est OK:

 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;
}
 

Je comprends ce que j'attends et mes arguments sont imprimés.

Cependant, si j'utilise _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;
}
 

Il affiche simplement le premier caractère de chaque argument.

Quelle est la différence causant cela?

353voto

jalf Points 142628

_tmain n'existe pas en C++. main .

_tmain est une extension Microsoft.

main , selon la norme C++, le programme du point d'entrée. Il a une de ces deux signatures:

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

Microsoft a ajouté un wmain qui remplace la deuxième signature avec ceci:

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

Et puis, pour le rendre plus facile de basculer entre Unicode (UTF-16) et de leurs caractères multioctets, ils ont défini _tmain qui, si Unicode est activé, est compilé en tant que wmain, et sinon, main.

Comme pour la deuxième partie de votre question, la première partie de l'énigme est que votre principale fonction est mal. wmain devrait prendre un wchar_t argument, et non char. Puisque le compilateur ne pas appliquer ce pour l' main fonction, vous obtenez un programme où un tableau de wchar_t chaînes sont passés à l' main de la fonction, qui les interprète comme char des chaînes de caractères.

Maintenant, en UTF-16, le jeu de caractères utilisé par Windows lors de l'Unicode est activée, tous les caractères ASCII sont représentés comme la paire d'octets \0 , suivie par la valeur ASCII.

Et depuis le CPU x86 est little-endian, l'ordre de ces octets sont inversés, de sorte que la valeur ASCII vient d'abord, puis suivi par un octet nul.

Et dans une chaine de caractères, quelle est la chaîne de caractères généralement fin? Yep, par un octet nul. Si votre programme voit un bouquet de chaînes de caractères, chacun des octets de long.

En général, vous disposez de trois options lorsque vous faites de la programmation sous Windows:

  • Explicitement l'utilisation de l'Unicode (appel wmain, et pour chaque fonction API Windows qui prend en char-les arguments d'appel de l' -W version de la fonction. Au lieu de CreateWindow, appel CreateWindowW). Et au lieu d'utiliser char utilisation wchar_t, et ainsi de suite
  • Désactiver explicitement Unicode. Appel principal, et CreateWindowA, et utiliser char pour les chaînes.
  • Permettre à la fois. (appel _tmain, et CreateWindow, résoudre à main/_tmain et CreateWindowA/CreateWindowW), et l'utilisation TCHAR au lieu de char/wchar_t.

La même chose s'applique à la chaîne de types définis par windows.h: LPCTSTR résout soit LPCSTR ou LPCWSTR, et pour chaque autre type qui comprend char ou wchar_t, a-T - version existe toujours, qui peut être utilisé à la place.

Il faut noter que tout ce qui est Microsoft. TCHAR n'est pas un standard du C++, c'est une macro définie dans windows.h. wmain et _tmain sont également définis par Microsoft.

35voto

Michael J Points 4112

_tmain est une macro qui obtient redéfini en fonction de si oui ou non vous compilez avec Unicode ou ASCII. C'est une extension Microsoft et n'est pas garanti de fonctionner sur n'importe quel autres compilateurs.

La déclaration correcte est

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

Si la macro UNICODE est définie, qui s'étend à

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

Sinon, il se développe pour

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

Votre définition va pour un peu de chaque, et (si vous avez UNICODE définie) s'étend à

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

qui est tout simplement faux.

std::cout travaille avec des caractères ASCII. Vous avez besoin de std::wcout si vous utilisez des caractères larges.

essayez quelque chose comme ceci

#include <iostream>
#include <tchar.h>

#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<argc; i++)
      _tcout << i << _T(" ") << argv[i] << std::endl;

   return 0;
}

Ou vous pouvez simplement décider à l'avance si l'utilisation ou à l'échelle de caractères étroits. :-)

Mis À Jour Le 12 Novembre 2013:

Changé le traditionnel "TCHAR" à "_TCHAR" qui semble être la dernière mode. Les deux fonctionnent très bien.

Mise À Jour De Fin

9voto

Paul Alexander Points 17611

la convention _T est utilisée pour indiquer que le programme doit utiliser le jeu de caractères défini pour l'application (Unicode, ASCII, MBCS, etc.). Vous pouvez entourer vos chaînes avec _T () pour les stocker dans le bon format.

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

5voto

CashCow Points 18388

Ok, la question semble avoir été entendu assez bien, l'UNICODE surcharge de prendre un large tableau de caractères comme second paramètre. Donc, si le paramètre de ligne de commande est - "Hello" qui serait probablement jusqu'à la fin comme "H\0e\0l\0l\0o\0\0\0" et votre programme d'imprimer uniquement l' 'H' avant qu'il voit ce qu'il pense est un terminateur null.

Alors maintenant, vous demandez peut-être pourquoi il même compile et des liens.

Eh bien, il compile parce que vous êtes autorisé à définir une surcharge d'une fonction.

La liaison est un peu plus complexe. En C, il n'est pas décoré symbole de l'information jusqu'à ce qu'il trouve une fonction appelée main. L'argc et argv sont probablement toujours là, comme la pile des appels paramètres, juste au cas où, même si votre fonction est définie avec la signature, même si votre fonction arrive à les ignorer.

Même si le C++ n'ont décoré des symboles, il est presque certainement utilise C-lien de main, plutôt que d'un savant éditeur de liens qui ressemble, pour chacun, à tour de rôle. Donc, il a trouvé votre wmain et de mettre les paramètres dans la pile des appels dans le cas où c'est l' int wmain(int, wchar_t*[]) version.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X