Toon posts:

[C++] Literal strings concatenaten

Pagina: 1
Acties:

Verwijderd

Topicstarter
Een bijzonder aspect van C++ (wat ik nooit op school geleerd heb) is dat je literal strings naar hartelust aan elkaar kunt plakken.

En wel zo:

C++:
1
2
string s = "123""123";
cout << s;


Resultaat: 123123

En ook:
C++:
1
2
const char* s = "123""123";
cout << s;


Resultaat: 123123

Waarom is dit zo? In Java is deze code ongeldig en moet je er een + tussen zetten.
Wie vertelt nu de compiler dat deze strings aan elkaar geplakt moeten worden?

Ik vond dit stukje code tijdens het programmeren in QT, waar ze het vaker gebruiken om niet over de horizontale grens over te gaan. (zoek naar: question() is useful for simple yes/no questions)

  • BtM909
  • Registratie: Juni 2000
  • Niet online

BtM909

Watch out Guys...

Is dat niet een kwestie van het volgende:
http://msdn2.microsoft.co...rary/69ze775t(VS.80).aspx
When specifying string literals, adjacent strings are concatenated. Therefore, this declaration:
C++:
1
char szStr[] = "12" "34";


is identical to this declaration:

C++:
1
char szStr[] = "1234";

[ Voor 21% gewijzigd door BtM909 op 08-01-2007 17:16 ]

Ace of Base vs Charli XCX - All That She Boom Claps (RMT) | Clean Bandit vs Galantis - I'd Rather Be You (RMT)
You've moved up on my notch-list. You have 1 notch
I have a black belt in Kung Flu.


Verwijderd

Volgens mij is dit gedaan omdat je in bepaalde situaties ook bijvoorbeeld literal strings en binaire code met elkaar wil combineren. Je kunt dan bij de declaratie gewoon meerdere waardes achter elkaar zetten.

Als jij dus meerdere literal strings achter elkaar wil zetten dan komt dat helemaal goed.

Edit:

Dat staat ook ongeveer wel beschreven in het linkie wat BtM909 gaf, ik ben dus -1 overbodig ;)

[ Voor 15% gewijzigd door Verwijderd op 08-01-2007 17:23 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14:58
Het is zo, omdat iemand het een handig idee vond en het aan de taal toevoegde. ;) Misschien niet het antwoord wat je verwachtte, maar veel meer valt er niet over te zeggen. Het is gewoon een handigheidje, net zoals het handig is dat je een integer literal met een expressie als 1 + 2 kunt schrijven in plaats van dat je verplicht 3 moet schrijven.

Het werkt trouwens ook in C, en is daarin handig om te gebruiken bij macro's, zodat je met de preprocessor ook string literals kunt produceren:
C:
1
2
3
4
5
6
7
8
9
#define HELLO(who) "Hello " who "!"
#define BYE(who) "Bye " #who "!"

int main()
{
    printf("%s\n", HELLO("world"));
    printf("%s\n", BYE(world));     /* Zonder quotes */
    return 0;
}


En als je lange stringconstantes in je programma wil stoppen, maar je wil je broncode wel netjes formatteren. Je kunt dan aan het einde van elke regel een backslash zetten en op de volgende verder gaan, maar als je ook wil inspringen kan je het dus ook zo doen:
C:
1
2
3
4
5
6
7
8
9
const char *somelargestring = 
    "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";

const char *anotherlargestring = 
    "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
    "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
    "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";

offtopic:
De C-parser van React kent de eerste variant blijkbaar niet.

[ Voor 9% gewijzigd door Soultaker op 08-01-2007 18:19 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:52

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op maandag 08 januari 2007 @ 18:16:
Het is zo, omdat iemand het een handig idee vond en het aan de taal toevoegde. ;) Misschien niet het antwoord wat je verwachtte, maar veel meer valt er niet over te zeggen. Het is gewoon een handigheidje, net zoals het handig is dat je een integer literal met een expressie als 1 + 2 kunt schrijven in plaats van dat je verplicht 3 moet schrijven.

Het werkt trouwens ook in C, en is daarin handig om te gebruiken bij macro's, zodat je met de preprocessor ook string literals kunt produceren:
C:
1
2
3
4
5
6
7
8
9
#define HELLO(who) "Hello " who "!"
#define BYE(who) "Bye " #who "!"

int main()
{
    printf("%s\n", HELLO("world"));
    printf("%s\n", BYE(world));     /* Zonder quotes */
    return 0;
}
Macro's zijn volgens mij ook de hele reden dat het ondersteund wordt in C en C++ :)
offtopic:
De C-parser van React kent de eerste variant blijkbaar niet.
offtopic:
Psst, die is niet van React ;)
Hmm, ik zou zweren dat ik het had ingebouwd.

C++:
1
2
3
4
5
#define aap noot
mies

#define aap2 noot2 \
mies2

offtopic:
Dat werkt blijkbaar wel.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14:58
offtopic:
Ik weet ook niet hoe het werkt of wie het geschreven heeft, ik weet alleen dat het niet werkt. ;)

Ik denk dat het probleem is dat de backslash binnen een token voorkomt? Volgens mij moet je wel in twee stages parsen om dit goed te doen, als het inderdaad zo is dat ik op deze manier ook andere tokens in tweeën mag splitsen. (Of je moet gewoon alle backslash-newline sequences vooraf wegfilteren, wat ook een extra pass is.)

Als work-around kun je waarschijnlijk wel gewoon die sequence in een string accepteren; in de praktijk breek je een regel verder natuurlijk alleen tussen twee tokens af.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:52

.oisyn

Moderator Devschuur®

Demotivational Speaker

offtopic:
voor strings gebruik ik sowieso een custom scanner die chars eet tot hij een " tegenkomt die niet volgt na een \ (de flex scanners voorzien daar in). Het is dus vrij simpel om dat uit te breiden zodat hij \ gevolgd door een \n ook mee-eet :).

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Verwijderd schreef op maandag 08 januari 2007 @ 17:12:
Wie vertelt nu de compiler dat deze strings aan elkaar geplakt moeten worden?
Niemand, want de compiler ziet maar één string literal! Het is de C/C++ preprocessor die ze aan elkaar plakt, niet de compiler.

Om nog even te reageren op de post van Soultaker: volgens mij is het zelfs zo dat in standaard C string literals niet voorbij het einde van een lijn mogen gaan (aka over meerdere lijnen gespreid mogen worden). Vandaar dat concatenatie bijna een must is. Maar heel zeker weten doe ik dat niet, ik herinner me enkel vaag iets in die aard. En ik ben nu even te lui om m'n specs op te graven :P
Soultaker schreef op maandag 08 januari 2007 @ 19:58:
offtopic:
Ik weet ook niet hoe het werkt of wie het geschreven heeft, ik weet alleen dat het niet werkt. ;)
offtopic:
Je kunt hier even kijken hoe het werkt want de source is beschikbaar. En de url geeft je een redelijk goede indicatie van de auteur ;)

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 18:11

crisp

Devver

Pixelated

.oisyn schreef op maandag 08 januari 2007 @ 22:20:
offtopic:
voor strings gebruik ik sowieso een custom scanner die chars eet tot hij een " tegenkomt die niet volgt na een \ (de flex scanners voorzien daar in). Het is dus vrij simpel om dat uit te breiden zodat hij \ gevolgd door een \n ook mee-eet :).
offtopic:
In jouw originele versie zat het iig niet, maar ik heb support ervoor er later zelf ingeklust met een FLAG_ESCAPE_NEWLINE flag. Dit gebruik ik echter atm enkel voor javascript omdat ik daarvan zeker wist dat het valid syntax was :P

Intentionally left blank


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14:58
Verwijderd schreef op dinsdag 09 januari 2007 @ 22:06:
Niemand, want de compiler ziet maar één string literal! Het is de C/C++ preprocessor die ze aan elkaar plakt, niet de compiler.
Hoe kom je daar nu weer bij?! Probeer het eens: echo '"foo" "bar" "baz"' | cpp; daar doet de preprocessor dus helemaal niets mee.

De compiler komt gewoon meerdere dezelfde tokens tegen, en genereert daarvoor code alsof het één string literal was. Dat werkt dus niet zoveel anders dan het voorbeeld wat ik al gaf: je kunt ook 1+2 schrijven om de integer literal 3 aan te duiden, net zoals je "foo" "bar" kunt schrijven om de literal "foobar" aan te duiden.
Om nog even te reageren op de post van Soultaker: volgens mij is het zelfs zo dat in standaard C string literals niet voorbij het einde van een lijn mogen gaan (aka over meerdere lijnen gespreid mogen worden). Vandaar dat concatenatie bijna een must is.
Niet als je die line continuation met backslash kunt gebruiken. (Maar ik gebruik 't daar zelf ook vaak voor, juist omdat je dan ook nog netjes kan inspringen zonder dat je whitespace in je string krijgt.)

[ Voor 4% gewijzigd door Soultaker op 10-01-2007 16:55 ]


Verwijderd

De C spec slecht gelezen? Of gaten in het geheugen! Of beide, wie zal het zeggen :+

Ik heb nog even gekeken, en dan vind ik dit onder "5.1.1.2 Translation phases":
...
6. Adjacent string literal tokens are concatenated.
7. White-space characters separating tokens are no longer significant. Each
preprocessing token is converted into a token. The resulting tokens are
syntactically and semantically analyzed and translated as a translation unit.
...

Dus in stap 7 converteren ze preprocessing tokens naar tokens, maar string literal concatenatie is de stap ervoor al gedaan. Snel lezen en/of een aangetast geheugen en je hebt het gedrag wat ik vertoonde ;)
Probeer het eens: echo '"foo" "bar" "baz"' | cpp; daar doet de preprocessor dus helemaal niets mee.
Inderdaad. Vreemd dat ik dat nooit geprobeerd heb. Normaal ben ik altijd een van de eersten om zo'n dingen aan de praktijk te toetsen. Damn, ik takel echt af :P

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:52

.oisyn

Moderator Devschuur®

Demotivational Speaker

crisp schreef op woensdag 10 januari 2007 @ 16:47:
[...]

offtopic:
In jouw originele versie zat het iig niet, maar ik heb support ervoor er later zelf ingeklust met een FLAG_ESCAPE_NEWLINE flag. Dit gebruik ik echter atm enkel voor javascript omdat ik daarvan zeker wist dat het valid syntax was :P
offtopic:
Ik kom binnenkort met een update, zodat C99, C++/CLI en C# 2.0 ook ondersteund worden :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1