How to Write the Range-based For-Loop With Argv? - c++

From the c++0x Wikipedia site:
int my_array[5] = {1, 2, 3, 4, 5};
for (int &x : my_array) {
x *= 2;
}
So why does this code not work?
int main(int argc, char* argv[])
{
for (char *arg : argv)
{
// Do something.
}
}
Error:
main.cpp:36: error: no matching function for call to ‘begin(char**&)’
I am using Qt with g++ 4.6.1 on Ubuntu 11.10.
Additional Information
Is There a Range Class in C++0x
Range-Based For-Loop Statement Definition Redundance

Usually, the first thing I do with argc and argv is this:
std::vector<std::string> arguments(argv, argv + argc);
Now I have a vector of strings to work with and I can easily use not only the range-based for loops, but also C++ standard library facilities.
for(std::string& s : arguments) {
// do stuff...
}
The wikipedia code works because the type of my_array is a variable of array type.
The original code does not work, because argv is not an array. The syntax char* argv[] may make it look like it is an array, but that's just a sad artifact of C syntax. char* argv[] is exactly the same as char** argv. argv is not an array; it's actually just a pointer.
The range-based for loop works on:
arrays;
any type that has member functions begin() and end() that return iterators;
any type for which exist non-member functions begin and end that can be called like begin(x) and end(x), with x being the thing that you're iterating over.
As you can see, pointers are not part of this list.

You don't, because the system can't tell how long argv is at compile time. Someone can likely find the proper section of the standard to quote you about this.
There is a way around it though, and that's to create a custom class to wrap argv. It's not even that hard.
class argv_range {
public:
argv_range(int argc, const char * const argv[])
: argc_(argc), argv_(argv)
{
}
const char * const *begin() const { return argv_; }
const char * const *end() const { return argv_ + argc_; }
private:
const int argc_;
const char * const *argv_;
};
Here's how you use it:
for (const char *arg: argv_range(argc, argv)) {
// Do something.
}
Yeah, I use a lot of consts. Basically, argv is an array of character pointers, none of which should be modified, each pointing to a string, none of the characters of which should be modified either.

The vector solution proposed copies the array (the pointers only, not the strings1 - but still). Unnessary. The argv_range solution is what I would have tried, too, if I absolutely wanted to enforce a range based loop. But that produces a lot of extra code (admitted, only once, if you write it to a header file and keep it, but still).
The classic loop appears so easy to me that I allow myself just to post it, I don't consider it worth to have all this effort just to have a range based loop...
for (char** a = argv; *a; ++a)
{
// use *a, or if you don't like:
char* arg = *a;
// use arg...
}
Or, if you won't ever need the argv array afterwards any more:
for (++argv; *argv; ++argv)
{
// use *argv, or if you don't like:
char* a = *argv;
// use a...
}
There is a little difference, you might have noticed: In the first variant, I iterate over all the values, in the second, I leave out the first one (which normally is the program name we are not interested in in many cases). The other way round, for each:
for (char** a = argv + 1; *a; ++a);
for (; *argv; ++argv);
Note that all these variants profit from the fact that the strings array itself is null-pointer-terminated as well, just as any of the strings is null-character-terminated, thus the simple checks for *a or *argv.
1This applies only, if using std::vector<char*>; if using std::vector<std::string>, as actually proposed, even the strings themselves are copied!

You can use C++20 std::span() or gsl::span() to make view for argv:
for (auto const arg : std::span(argv, argc)) {
std::cout << arg << '\n';
}
Or similar, using Ranges (std::view::counted()):
for (auto const arg : std::views::counted(argv, argc)) {
std::cout << arg << '\n';
}
or directly using std::ranges::subrange:
for (auto const arg : std::ranges::subrange{argv, argv+argc}) {
std::cout << arg << '\n';
}

argv is a double pointer, argv**
So where &x creates a reference to the element in the array, your *arg does not create a reference but rather is the same type as every element in argv.

I take you'd like the range based loop in order to not have to write that much..
so to annoy c++ purists, while at the same time not exactly answering your question, we'd like to post some nicely unsafe ways to do it without any std::vector or OO-wrapper-crap :)
for (;argc--; argv++) {
printf(" %s \n ", *argv);
}
or
while (argc--) {
printf(" %s \n ", *(argv++));
}
or even
while (*argv) {
printf(" %s \n ", *(argv++));
}

Related

Printing argv with forrange loop

int main(int argc, const char** argv) {
std::cout << "Hello" << std::endl;
char arr2d[][4] = {"ABC", "DEF"};
for (char *i : arr2d)
{
std::cout << i << std::endl;
}
In here, I evaluate the job of forrange as this: "For each character array in arr2d, print it it to console". And this works, so, my understanding, at least, should be correct. The output to the above code snippet is,
muyustan#mint:~/Desktop/C_Files/oop$ g++ main.cpp -o main && ./main
Hello
ABC
DEF
as expected.
However, if I try this one,
int main(int argc, const char** argv) {
std::cout << "Hello" << std::endl;
char arr2d[][4] = {"ABC", "DEF"};
for (const char *i : argv)
{
std::cout << i << std::endl;
}
First the IDE warns me with,
this range-based 'for' statement requires a suitable "begin" function and none was found
And if I try to compile, I get:
muyustan#mint:~/Desktop/C_Files/oop$ g++ main.cpp -o main && ./main
main.cpp: In function ‘int main(int, const char**)’:
main.cpp:30:26: error: ‘begin’ was not declared in this scope
for (const char *i : argv)
^~~~
main.cpp:30:26: note: suggested alternative:
In file included from /usr/include/c++/7/string:51:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:1:
/usr/include/c++/7/bits/range_access.h:105:37: note: ‘std::begin’
template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
^~~~~
main.cpp:30:26: error: ‘end’ was not declared in this scope
for (const char *i : argv)
^~~~
main.cpp:30:26: note: suggested alternative:
In file included from /usr/include/c++/7/string:51:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:1:
/usr/include/c++/7/bits/range_access.h:107:37: note: ‘std::end’
template<typename _Tp> const _Tp* end(const valarray<_Tp>&);
So, why argv behaves differently than my arr2d[][4] ? Aren't both of them pointers of char pointers(char arrays or strings(?)) ?
And if something wrong with my understanding, what should be the structre of printing ingreditens of argv with a forrange?
this is something I have been told wrong then, when I was dealing with C back then, at somewhere I have read that "arrays are also pointers!".
There are couple of finer points one must understand regarding that statement.
Arrays decay to pointers in most contexts and but arrays are still different than pointers.
When used as argument to sizeof, the following two will result in different answers.
char const* ptr = "Some text.";
char array[] = "some text.";
std::cout << sizeof(ptr) << std::endl; // prints sizeof the pointer.
std::cout << sizeof(array) << std::endl; // prints sizeof the array.
When used as an argument to the addressof operator.
char const* ptr1 = "Some text.";
char array[] = "some text.";
char const** ptr2 = &ptr1; // OK.
char** ptr3 = &array; // Error. Type mismatch.
char (*ptr4}[11] = &array; // OK.
2D arrays can decay to pointers to 1D arrays but they don't decay to pointers to pointers.
int array1[10];
int* ptr1 = array1; // OK. Array decays to a pointer
int array2[10][20];
int (*ptr2)[20] = array2; // OK. 2D array decays to a pointer to 1D array.
int** ptr3 = array2; // Error. 2D array does not decay to a pointer to a pointer.
They behave differently because they have different types. This is confusing for beginners, but:
char **
is a pointer to pointer to char. In fact, in the case of argv, it is pointing to a sequence of pointers, each pointing to a nul-terminated string (which are sequences of characters).
The problem iterating those is that the size of those sequences is not known. The compilers cannot know argc is related to the first sequence mentioned above.
However:
char arr2d[][4] = {"ABC", "DEF"};
resolves to the type:
char [2][4]
Which is an array of arrays of char. In this case, the size is known (2), so you can iterate over it.
Finally, the compiler complains about std::begin because the range-based for loop is transformed into different equivalent code which uses std::begin etc. to do the iteration.
If you want to apply a range-based for to argv, it's probably easiest if you start by creating a vector containing the arguments:
#include <iostream>
#include <vector>
int main(int argc, char **argv){
std::vector<std::string> args(argv, argv+argc);
for (auto const &arg : args) {
std::cout << arg << "\n"; // don't use `endl`.
}
}
As far as argv compared to a 2D array, the difference is fairly simple. When you have an array declaration, the array can be passed by reference to a template, which can figure out its size:
template <class T, size_t N>
size_t array_size(T (&array)[N]) {
return N;
}
int foo[2][3];
std::cout << array_size(foo) << "\n";
char bar[12][13][14];
std::cout << array_size(bar) << "\n";
...but, argv doesn't have a statically visible definition like that, from which the compiler would be able to deduce its size. In a typical case, there's code that runs outside main that inspects the command line, and allocates it dynamically instead.
The range-for expression works with iterators (pointers are a type of iterator), and it requires an iterator to the beginning and end of the range. It obtains those by passing the range to std::begin and std::end.
The type of arr2d is char[2][4]. As an array, it carries information about its size as part of its type. There are template overloads for std::begin and std::end that accept a reference to an array and return a pointer to its first and one-past-the-last element, respectively.
The type of argv is char**. It's just a pointer to a pointer to a char. The compiler has no idea either of those pointers point to the first element of an array, and these pointers carry no information about the length of the array that they point to. As such, there are no overloads of std::begin and std::end that accept a pointer since there's no way for std::end to figure out where the end of the array is in relation to the beginning from a pointer alone.
To use pointers with a range-for, you must provide the information about the array's length. In this case, you could construct a simple view over the array, since you know its length from argc:
template <typename T>
class PointerRange
{
private:
T* ptr_;
std::size_t length_;
public:
PointerRange(T* ptr, std::size_t length)
: ptr_{ptr},
length_{length}
{
}
T* begin() const { return ptr_; }
T* end() const { return ptr_ + length_; }
};
int main(int argc, char** argv)
{
for (char* arg : PointerRange(argv, argc)) {
std::cout << arg << "\n";
}
}
Live Demo
Once C++20 becomes available, std::span can take the place of the PointerRange defined above:
int main(int argc, char** argv)
{
for (std::string_view arg : std::span{argv, argc}) {
std::cout << arg << "\n";
}
}
If your compiler has the span header (not a lot of them do right now) I imagine this would work.
// Example program
#include <iostream>
#include <string_view>
#include <span>
int main(int argc, char **argv)
{
for (std::string_view s : std::span{argv, argc})
{
std::cout << s << std::endl;
}
return 0;
}
The only overhead with my example is having string_view find the null terminal. I tried it goldbolt.org but it seems that none of the compilers can find the span header. So take my advice lightly.

C++ behavior that I don't understand

My friends and I were playing with the C++ language. While doing so, we encountered something we couldn't understand.
Here is the code:
#include <vector>
#include <iostream>
void print(std::vector<char> const &input)
{
std::cout << input.size();
for (int i = 0; i < input.size(); i++)
{
std::cout << input.at(i) << " - ";
}
}
int main()
{
char cha = 'A';
char chb = 'B';
char * pcha = &cha;
char * pchb = &chb;
try
{
std::vector<char> a = {pcha, pchb};
//std::vector<char> a = {pchb, pcha};
print(a);
}
catch(std::exception e)
{
std::cout << e.what();
}
}
Output for this code:
A
When I comment out this first line try block and uncomment the second line, which comes to this:
try
{
// std::vector<char> a = {pcha, pchb};
std::vector<char> a = {pchb, pcha};
print(a);
}
Output becomes:
std:exception
I thought maybe the this occurs because of the different padding and alignments of the declared variables (char, char*), yet still didn't understand. You can find the code here to play around.
Thanks in advance.
std::vector<char> a = {pcha, pchb};
Here, you use the constructor of vector that accepts two iterators to a range. Unless the end iterator is reachable from the begin one, the behaviour of the program is undefined. Your two pointers are not iterators to the same range (i.e. elements of an array), so one is not reachable from the other. Therefore the behaviour of the program is undefined.
These would be correct:
std::vector<char> a = {cha, chb}; // uses initializer_list constructor
// or
char arr[] {cha, chb};
char * pcha = std::begin(arr);
char * pchb = std::end(arr);
std::vector<char> a = {pcha, pchb}; // uses the iterator constructor
#eerorika's answer explains your mistake.
However, I would like to dissuade you, and other readers, from using the second part of the his(?) corrected code snippet - not because it's incorrect, but because it's problematic coding practice:
I accept Nicolai Jossutis' suggestion of trying to uniformly initialize variables with curly brackets and no equals since (e.g.. mytype myvar {my_initializer};).
Freestanding pointers are dangerous beasts. Try to avoid them altogether, or minimize their existence to where you really need them. After all, you were "tempted" to use those pointers in an inappropriate way... so,
char arr[] {cha, chb};
std::vector<char> a = {std::begin(arr), std::end(arr)};
Don't create a dummy container just to create the one you really want. Just stick with the first line in #eerorika's suggestion (without the equals sign):
std::vector<char> a {cha, chb};
In fact, unless you really need it - you probably don't even want to create a variable-length container. So perhaps just
std::array<char, 2> a {cha, chb};
or with C++17's template argument deduction:
std::array a {cha, chb};

C++: how to read **argv value and copy into a string

I'm making a new app for my lab and I must take form terminal some arguments, and I want to copy the **args value into a string, and after that I must match the args for execute some foreplay operation.
I try to build this code to copy the **argv value into string var but this is the error:
No source available for "std::string::operator=() at 0x44c1dc"
The code is this:
int main(int argc, char **argv)
{
string args[argc-1];
int j=0;
for(int i=2; i<argc-1;i++)
{
j=0;
while(argv[i][j]!='\0')
{
args[i]=args[i]+argv[i][j];
j++;
}
}
return 0;
}
I would propose this solution:
std::vector<std::string> args;
std::copy(argv + 1, argv + argc, std::back_inserter(args));
References:
std::copy
std::back_inserter
To explain it a little, this copies from argv[1] (I don't care about argv[0] as it's the "command" and usually irrelevant for argument handling) into the vector. We stop copying at argv[argc] which is one beyond the end of the actual arguments (which is how "end" iterators work).
std::back_inserter creates a special iterator that is used to insert ad the end of containers.
Fastest and shortest solution with range constructor:
std::vector<std::string> args(argv + 1,argv + argc);
Make things as clear as you can. (Will help those 3am debugging sessions in your laboratory).
int main(int argc, char **argv)
{
std::vector<std::string> args(argc);
for (int i = 0; i < argc; ++i){
args[i] = argv[i];
}
// rest of code here.
}
Yes I know I waste args[0], but do you really care about that? The indexing is so much clearer if you do it this way, args has the same indexing conventions as argv (which all us old cats are used to), and you don't get a whole lot of edge cases when you only pass the program name.
There are a few mistakes in your code, which also causes the odd problems. Also you're overcomplicating things quite a bit.
Here's what I'd do, this will require one additional header, <vector>, for the STL container, but it will make things a lot easier (since you shouldn't rely on being able to create arrays with dynamic lengths (also note that your array length might be 0, if there are no arguments given!))
int main(int argc, char **argv) {
std::vector<const std::string>> params; // This is the container that will take all arguments.
// Iterate over all arguments provided
// (skipping the very first, since that's the executable itself)
for (int i = 1; i < argc; i++)
// Add the argument to the vector
// (this will construct a new std::string and add it to the end).
params.push_back(argv[i]);
// You're now able to access the arguments passed:
// params.size() will return the number of arguments.
// params[i] will return the i-th argument, starting at 0.
return 0;
}
int main(int argc, char **argv)
{
string args[argc];
int j=0;
for(int i=2; i<argc;i++)
{
args[i-2].assign(argv[i]);
}
return 0;
}
first, you can't use a dynamic argument in a static expression.
you must use either new to create a string array, or, better yet, use a vector (or any other container you like).
second, there is no point in copying the values one character by another. copy the entire string.
here is a sample code that will work:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef vector<string> svec;
int main(int argc,char **argv)
{
svec strings;
if(argc>1)
{
cout <<"arguments:"<<endl;
for(int i=1;i<argc;i++)
{
strings.push_back(argv[i]);
}
}
for(auto i:strings)
{
cout << i;
}
return 0;
}
D.

How to make char array and std::string "in a relationship"?

I'm looking for a way to associate a char array with a string so that whenever the char array changes, the string also changes. I tried to put both char array and string variables in a union but that didn't worked as the compiler complained...
Any ideas are welcome...
class Observable_CharArray
{
char* arr;
std::function<void(char*)> change_callback;
public:
Observable_CharArray(int size, std::function<void(char*)> callback)
: arr(new char[size]), change_callback(callback){}
~Observable_CharArray()/*as mentioned by Hulk*/
{
delete[] arr;
}
void SetCallback(std::function<void(char*)> callback)
{
change_callback = callback;
}
/*other member function to give access to array*/
void change_function()
{
//change the array here
change_callback(arr);
}
};
class Observer_String
{
std::string rep;
void callback(char* cc)
{
rep = std::string(cc);
}
public:
Observer_String(Observable_CharArray* och)
{
och->SetCallback(std::bind(&callback, this, _1));
}
/*other member functions to access rep*/
};
The design can definitely be improved.
There can be other ways to solve your actual problem rather than observing char arrays.
The problem is that the std::string may change the string array inside (especially when it resizes). For instance, c_str returns the address of the current string - documentation says that "The pointer returned may be invalidated by further calls to other member functions that modify the object.".
If you're sure you won't call string methods (hence the string will stay at the same memory location), you could try accessing the c_str pointer (your char array) directly and modify its content.
std::string str = "test";
char* arr = (char*)str.c_str();
arr[3] = 'a';
NOTE: I strongly advice against this unless in a testing context.
In other words, the string class doesn't guarantee it's going to stay in the same place in memory - meaning trying to access it through a char array is impossible.
The best is to create another string class that enforces the char array to always stay the same size (and so can stay in the same memory position all the time). You could also create a bigger array (max size string for instance) to cope with any string size changes - but that should be enforced in your wrapper class.
Well you can do this, but you shouldn't
#include <iostream>
#include <string>
int main()
{
std::string test("123456789");
std::cout << test << "\n";
char* data = &test.front(); // use &(*test.begin()) for pre-C++11 code
for ( size_t i(0); i < test.size(); ++i )
{
data[i] = 57 - i;
}
std::cout << test << "\n";
}
Output will be
123456789
987654321
This however goes again everything std::string is trying to facilitate for you. If you use data, you risk causing UB and changes to test may make data point to garbage.
You should not do this!
However, there are many (dangerous) ways to achieve it:
char* cStr = const_cast<char*>(cppStr.c_str());
or
char* cStr = const_cast<char*>(cppStr.data());
or
char* cStr = &cppStr[0];
But beware that the cppStr might be reallocated whenever you touch it, hence invalidating your cStr. That would crash at some point in time, although maybe not immediately (which is even worse).
Therefore, if you are going to do this anyway. Make sure to cppStr.reserve(SOMETHING) *before* you get the cStr out of it. This way, you will at least stabilise the pointer for a while.

How to initialize last item automatically in a struct array?

I am passing an array to a function, and i am initializing it globally with some values.
I am using empty string in end of array to determine the array length.
Now, Is there some way to automatically initialize the array to have extra empty item in the end of it, so i have no chances to forget it from there? Just like the char[] works, it adds extra null to the end IIRC.
Here is my code what im using now:
struct twostrings {
string s1, s2;
};
twostrings options[] = {
{"text1", "more text1"},
{"text2", "more text2"},
{"text3", "more text3"},
{""}, // tells that the array ends here
}
int get_len(twostrings opt[]){
int p = 0;
while(1){
if(opt[p].s1 == ""){
return p;
}
p++;
// now here is a possibility to go in infinite loop if i forgot the empty string.
// currently i have a code here that checks if p > 10000 and gives error message to me if i manage to forget that empty string in accident.
}
return p;
}
void dosomething(twostrings options[]){
int len = get_len(options);
for(int p = 0; p < len; p++){
// do stuff
}
}
int main(){ // yes its not valid written main function. dont bother about it.
dosomething(options);
}
Passing around C arrays is not very idiomatic in C++. Try using a std::vector instead:
#include <vector>
#include <string>
struct twostrings {
std::string s1, s2;
};
typedef std::vector<twostrings> option_type;
twostrings options[] = {
{"text1", "more text1"},
{"text2", "more text2"},
{"text3", "more text3"}
};
int get_len(const option_type& options){
return options.size();
}
void dosomething(const option_type& options){
int len = get_len(options);
for(int p = 0; p < len; p++){
// do stuff
}
}
int main() { // This main function is perfectly fine!
option_type opt_vector(options, options + (sizeof options / sizeof options[0]));
dosomething(opt_vector);
}
Unforunately, you're not correct. The char array does not end automatically in a null, this is only a side effect of assigning it with a string literal (which has the automatic null at the end).
char x[] = "ABC"; // size 4, contains A, B, C, \0.
char x[] = {'A','B','C'}; // size 3, contains no terminating null.
So the short answer is no, there's no way to automatically end arrays with an automatic entry. There are a bunch of other options though, such as STL vectors which have other means of determining when you've reached the end. In C++0x there'll probably (IIRC) be a way to initialize the vector just like you'd like.
HTH.
EDIT:
Personally, I prefer to add the extra 0 at the end of the array myself, but I suppose there are ways to work around it using macros.
#define ARRAY(...) {__VA_ARGS__, {0}}
and use it like so
struct foo { char* x; char* y; }
struct foo x[] = ARRAY({"abc", "xyz"}, {"def","uvw"});
I have no idea if this works (and I have no preprocessor handy), and as I said, personally I don't like it. It also requires the first element in the struct to be something which can be assigned 0 to mark the end of the array.
Of course, this forces you to remember to wrap it in the macro call, which is pretty much as bad as forcing you to remember to terminate the array.
EDIT:
I just had a chance to test this and it works. Turns out variadic macros are, so far anyway, C only. However some (most?) C++ compilers support them anyway, a quick search turned up g++ and visual studio. Still I wouldn't favor this approach, I just added it for completeness.
Pass the length or the end instead of using a sentinel:
template<class T, int N>
int len(T (&)[N]) { // exists in a more general form as boost::size
return N;
}
typedef std::pair<std::string, std::string> twostrings;
// std::pairs have first and second members of the given types
void dosomething(twostrings options[], int size);
// call as: dosomething(array, len(array));
# or:
template<class T, int N>
T* end(T (&a)[N]) { // exists in a more general form as boost::end
return a + N;
}
void dosomething(twostrings* options_begin, twooptions* options_end);
// call as: dosomething(array, end(array));
// usage example:
void dosomething(twostrings* options_begin, twooptions* options_end) {
// you might name the parameters just 'begin' and 'end'
for (; options_begin != options_end; ++options_begin) {
// the 'begin' var advances through the entire sequence
// use for (twostrings* current = options_begin; current != options_end; ++current)
// if a separate copy is required
cout << options_begin->first << ": " << options_begin->second << '\n';
}
}
Note the [begin, end) iterator pattern (that's inclusive begin, exclusive end) is common in the stdlib (e.g. look at std::sort from <algorithm>).
This is a good halfway measure between arrays and containers such as std::vector, and allows you to keep the easy initialization syntax you have now (C++0x gives you that same syntax with containers such as std::vector, but 0x is not quite yet ready).
Don't use C style arrays in C++, they're just not worth the effort compared to vector.size(). You should use a boost::array<twostrings, length> for a static array.
Hell, you should probably just not use a static value.
There are better ways of finding array lengths. You can use:
1. sizeof(options) / sizeof(twostrings);
2. sizeof(options) / sizeof(options[0]);
3. std::vector<twostrings> options;
options.size();
4. ARRAYSIZE(options); (windows only)
Btw, if(opt[p].s1 == "") is checking 2 const char * pointers for equality, not 2 strings. Although compiller usualy optimizes equal string constants to point to one place, it is still an error.
You should use a NULL sentinell as it was adviced by Svisstack earlier.
edit: Proof
#include <stdio.h>
const char *one = "the string";
void main(){
const char *other = "the string";
printf("adress of 'one' = %x, it contains \"%s\"\n", one, one);
printf("adress of 'other' = %x, it contains \"%s\"\n", other, other);
if(one == other){
printf("one == other\n", one);
} else {
printf("one != other\n", one);
}
}
Output:
k:\temp>cl test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
/out:test.exe
test.obj
k:\temp>test.exe
adress of 'one' = 3d8140, it contains "the string"
adress of 'other' = 3d814c, it contains "the string"
one != other