• Advertisement
Sign in to follow this  

Anyone know about this random little feature of C?

This topic is 4735 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Found this out at university today, not one of the lecturers knew about it, nor the tutors (one of the students did it in a tutorial) anyway, this is completly valid code in C/C++:
printf("how"
       "are"
       "you?");
C concats the strings automagically for you. so;

void doStuff(char * text)
{
    // blag
}

void main()
{
   doStuff("I" "am" "fine");
}

is also fine. Weird huh? maybe it's just me, but to me, thats really really bad, the compiler effectivly changes your code.

Share this post


Link to post
Share on other sites
Advertisement
Well think about what you are saying there.

Your memory locations will look something like this (Char* purechar Char* purechar Char* purechar )

None of those has a \0 on the end of it so it'll read til it doesn't find characters any more. So it skips to the second group of characters. Does it output "Iamfine" or does it output it with spaces?

Remember the compiler never officially changes your code, it just interprets it, and if this functionality is in here (and it appears to be) it was supposed to be here, especially in something so overly used as printf.

Share this post


Link to post
Share on other sites
I use that feature frequently for long constant strings. I hate having my constant messages stretch right off the side of the screen so I do that. ;)
And like was said before thats how the compiler interprets it. It is just a long string. If you put ,'s or ;'s in between then it would be interpreted differently.

Share this post


Link to post
Share on other sites
I knew about that. I think it's great for breaking apart long lines, to keep the code neat and readable. Don't remember how I first found out about it though.

Then again, I haven't really used it since I started using C++ streams, I just do something like this:

cout << "I"
<< " am "
<< " fine " << endl;

In order to break up any long character strings and keep things readable.

Fun stuff!

Share this post


Link to post
Share on other sites
Quote:
Original post by RipTorn
maybe it's just me, but to me, thats really really bad, the compiler effectivly changes your code.

I'm not sure why you think it changes your code; it's just a feature of the laguage like anything else, you just haven't run into a good use for it yet. Most-commonly, you'll only be using it on either really long strings that would extend very far on one line, or if you are working with the preprocessor and want to concatenate two strings together. One quick example use would be:

#include <iostream>

#define ERROR_MESSAGE( error_message ) "Error: " #error_message

int main()
{
::std::cout << ERROR_MESSAGE( divide by zero );

// Same as

::std::cout << "Error: divide by zero";
}








Quote:
Original post by RipTorn

void main()
{
doStuff("I" "am" "fine");
}



is also fine.

Actually that is not fine, since void main is neither valid C nor C++. The main function must have the return type int in C and C++ (though many non-compliant compilers support void main, it is not standard).

Share this post


Link to post
Share on other sites
It's not weird at all, it's pretty useful in fact and is fairly widely used. I'm surprised nobody at your university had seen it before. It's particularly useful for doing something like this:


const char* helpText =
"This is some multi-line help text that you wouldn't want to squeeze onto one \n"
"line in the source code. Think about how you'd have to lay out a string like this \n"
"if C/C++ didn't support automatic concatenation of string literals. The concatenation \n"
"happens at compile time, not at runtime, so the compiler isn't changing your code at \n"
"all, it's just saving you from having lines hundreds of characters long in your source. \n";


Share this post


Link to post
Share on other sites
I use it a occasionally. It is handy for building strings with macros. Saying the the compiler changes your code is not correct, since putting two strings together like that tells the compiler to concatenate them.

The only drawback is that bugs like this happen a lot:
char * array[] =
{
"1",
"2",
"3",
"4"
"5",
"6"
};
The above array has only five elements. Oops.

Share this post


Link to post
Share on other sites
Quote:
Original post by Polymorphic OOP
Actually that is not fine, since void main is neither valid C nor C++. The main function must have the return type int in C and C++ (though many non-compliant compilers support void main, it is not standard).
Legality of void main().
I just felt like counter-nitpicking..

Share this post


Link to post
Share on other sites
Quote:
Original post by cgoat
I knew about that. I think it's great for breaking apart long lines, to keep the code neat and readable. Don't remember how I first found out about it though.

Then again, I haven't really used it since I started using C++ streams, I just do something like this:

cout << "I"
<< " am "
<< " fine " << endl;

In order to break up any long character strings and keep things readable.

Fun stuff!

Not that this is something that really needs optimizing but still, using streams for this is horrendously inefficient by comparison since string literals are concatenated by the compiler at compile time and so there is no runtime cost whereas doing it this way requires a function call for every concatenation.

Share this post


Link to post
Share on other sites
I didn't mean to imply that the iostreams were better or anything... just a comment on how I hadn't used that particular language feature since starting to use iostreams more often.

Share this post


Link to post
Share on other sites
I've known about that for a while. You can do it in python, too:

print "Hi\n" \
"Hello\n"



Share this post


Link to post
Share on other sites
Well thats a surprise.
Absolutly no one I talked to knew about it, and everyone thought it was a bad idea. Yes it has uses, but it just 'feels' wrong, and while it may be correct memory wise (barly), if the strings really were char*'s, then it should be highly illegal code. (special cases of any sort are bad imo)

Maybe it's just because we are all used to strict managed languages I guess.

never mind then.

Share this post


Link to post
Share on other sites
The only reason it appears wrong to anyone is that we're all so used to C and C++ being low-level. The idea of C++ doing something FOR us feels wrong. In reality, it's a perfectly practical feature. Why not have the ability to use a long-ass string without compromising code readability and/or CPU cycles?

Share this post


Link to post
Share on other sites
I use that a feature alot. You want to see a strange feature, try


int array[2];
int first=0, second=1;
first[array] = 42;
second[array] = 54;





I have no idea how that creeped into the language.

Share this post


Link to post
Share on other sites
Quote:
Original post by mattnewport
Quote:
Original post by cgoat
I knew about that. I think it's great for breaking apart long lines, to keep the code neat and readable. Don't remember how I first found out about it though.

Then again, I haven't really used it since I started using C++ streams, I just do something like this:

cout << "I"
<< " am "
<< " fine " << endl;

In order to break up any long character strings and keep things readable.

Fun stuff!

Not that this is something that really needs optimizing but still, using streams for this is horrendously inefficient by comparison since string literals are concatenated by the compiler at compile time and so there is no runtime cost whereas doing it this way requires a function call for every concatenation.


Are you sure the C++ compiler won't concatenate those string literals at compile time?

Share this post


Link to post
Share on other sites
Quote:
Original post by smart_idiot
I have no idea how that creeped into the language.

I think it has to do with the mechanic of the [] operator. It is valid for the array and index to be in either position. I don't see how it's of any use and would just make the code more confusing.

Share this post


Link to post
Share on other sites
Quote:
Original post by RipTorn
Well thats a surprise.
Absolutly no one I talked to knew about it, and everyone thought it was a bad idea. Yes it has uses, but it just 'feels' wrong, and while it may be correct memory wise (barly), if the strings really were char*'s, then it should be highly illegal code. (special cases of any sort are bad imo)

Maybe it's just because we are all used to strict managed languages I guess.

never mind then.

If you understand how string literals are treated by the compiler in C/C++ then it doesn't 'feel' wrong. When the compiler encounters a string literal it allocates space for the characters in a special section of the object file (usually either .text where the actual code lives or .rodata, the read-only data section) and copies the character data there. The string literal is then substituted for a const char* that points to the actual character data in the object file. All that happens when you have "two " "strings" with nothing but whitespace separating them is that your string literal is specified in several pieces which the compiler concatenates and the resulting concatenated string literal is placed in the object file. From that point on everything happens exactly the same as if you'd specified the string inside a single set of quotes - the string literal is substituted with a single const char* pointing to the character data and the resulting code is identical.

Share this post


Link to post
Share on other sites
Quote:
Original post by Boder
Are you sure the C++ compiler won't concatenate those string literals at compile time?

I wouldn't bet my life on it but I think it's highly unlikely any current compiler does it. When you use streams you're using library code, not a built in language construct. Unless the compiler has special case code for handling standard library classes (which I think is very unlikely) it would have to inline all those function calls and collapse all the concatenation code (which probably involves dynamic memory allocation) down to it's result. I'll give it a try in VC though - it has surprised me before with it's ability to eliminate redundant code.

Share this post


Link to post
Share on other sites
There we go, not too hard to work that one out was it, now onto the real dodgy problem:
Quote:
first[array]

Share this post


Link to post
Share on other sites
Quote:
Original post by mattnewport
I'll give it a try in VC though - it has surprised me before with it's ability to eliminate redundant code.

Nope, tried it out in VC.NET 2003 with optimizations cranked up to the max (including WPO/LTG) and it doesn't concatenate the strings. It doesn't even inline the function calls.

Share this post


Link to post
Share on other sites
Quote:
Original post by ZedFx
There we go, not too hard to work that one out was it, now onto the real dodgy problem:
Quote:
first[array]


array[first] ==
*(array + first) ==
*(first + array) ==
first[array]

Share this post


Link to post
Share on other sites
In that case it would be better to do


cout << "I"
" am "
" fine " << endl;

Share this post


Link to post
Share on other sites
Quote:
Original post by bakery2k1
Quote:
Original post by ZedFx
There we go, not too hard to work that one out was it, now onto the real dodgy problem:
Quote:
first[array]


array[first] ==
*(array + first) ==
*(first + array) ==
first[array]

AH-HAH! I was tryin' to remember WHY that was legal.

Share this post


Link to post
Share on other sites
Quote:
Original post by Boder
In that case it would be better to do


cout << "I"
" am "
" fine " << endl;

Yep. So it really is a useful feature after all [smile]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by smart_idiot
I use that a feature alot. You want to see a strange feature, try

*** Source Snippet Removed ***

I have no idea how that creeped into the language.


In asm x86 there are something similar

[bx + 4] == [bx]4 == 4[bx]

and other fun things with arrays and indexing that I don't remember

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement