Comments (13)
Hi, @Zjianglin. got your reply.
- First question:
Why not use address-of operator (&)?
All of the snippets here are used to prove that STL algorithm equal
shouldn't be applied to const char*
(or char*
) because the result depends on platforms. As @Mooophy put it:
For such case, std::equal is going to compare the address value rather than the string value. ...
Thus the snippets try to output the real value a const char*
pointer holds, to prove the values of elements in two vector<const char*>
depend on platforms. The real value of an element in vector<const char*>
is an address value, so we are trying to output address values. To get such values, we cannot directly use the code below:
const char* cstr = "c style string";
cout << cstr << endl;
Because cout
will output the string literals a const char*
pointer points to rather than the address value(see this answer), we have to convert a const char*
pointer to const void*
pointer. The address-of operator &
is not helpful because it evaluates the address of a pointer resides rather than the value the pointer holds. The table below best explains everything:
Symbol *cstr cstr &cstr
Memory Value ['c'] [1000] [1004]
Memory Address 1000 1004 1008
Here we want 1004
, but &cstr
yields 1008
. For this reason, I don't use &
operator.
- Second question
Why the anonymous object
static_cast
generates could indicate the original element(cs)'s address?
The link above has given a very detailed explanation. I guess you confuse the address a pointer holds and the address the pointer resides. Here we are only interested in the former. The latter doesn't matter to us.
This is a little messy. Hope my reply doesn't increase your confusions if it doesn't ease them.
from cpp-primer.
I compiled the following program with g++
and cl
respectively.
#include <iostream>
#include <vector>
#include <algorithm>
using std::cout;
using std::endl;
using std::vector;
int main()
{
// just for explanation, don't use this way.
vector<const char*> roster1 = { "C++", "Primer", "Plus" };
vector<const char*> roster2 = { "C++", "Primer", "Plus" };
cout << "Two const char arrays are "
<< (equal(roster1.cbegin(), roster1.cend(), roster2.cbegin()) ? "equal" : "not equal") << endl;
cout << "Address of roster1: ";
for(const auto &cs : roster1)
cout << static_cast<void*>(cs) << " ";
cout << endl;
cout << "Address of roster2: ";
for(const auto &cs : roster2)
cout << static_cast<void*>(cs) << " ";
cout << endl;
return 0;
}
With g++
, the result is:
Two const char arrays are equal
Address of roster1: 0x4ab07e 0x4ab082 0x4ab089
Address of roster2: 0x4ab07e 0x4ab082 0x4ab089
With cl
, the result is:
Two const char arrays are not equal
Address of roster1: 00A4F190 00A4F194 00A4F19C
Address of roster2: 00A4F1A4 00A4F1A8 00A4F1B0
Obviously, this depends on compiler. It accords with @CyberLuc's result. Thank you!
from cpp-primer.
thanks !!
from cpp-primer.
@CyberLuc I couldn't agree more. 👍
from cpp-primer.
I admire @CyberLuc 's strong skill at such low level, hoping @CyberLuc make more contribution for us. The example given above is great as well.
As for this issue, can we change the current answer like below?
For such case, std::equal is going to compare the address value rather than the string value. So the result is not the same as
std::string
. Try to avoid coding this way.
from cpp-primer.
Thank you for your praise! 😄
And yeah, the updated answer is good! 👍
from cpp-primer.
@chihyang hi, I tried to test your code, but encountered compile error as below.
$ clang++ -std=c++11 test.cpp -o maintest.cpp:16:17: error: static_cast from 'const char *' to 'void *' is not
allowed
cout << static_cast<void*>(cs) << " ";
^~~~~~~~~~~~~~~~~~~~~~
test.cpp:20:17: error: static_cast from 'const char *' to 'void *' is not
allowed
cout << static_cast<void*>(cs) << " ";
^~~~~~~~~~~~~~~~~~~~~~
2 errors generated.
It's same to g++ compiler. How did you get your output, or did I do somethig error? Thanks.
from cpp-primer.
@Zjianglin Hi, I usually used the following commands when I learned the primer (supposing the directory obj
exists in current path):
g++ -std=c++11 -Wall -o <output> <input>
clang++ -std=c++11 -stdlib=libstdc++ -Wall -o <output> <input>
cl -EHsc -W4 <input> -Fo./obj/ -Fe./obj/
And the compiler versions I used are as follows:
g++: (tdm64-1) 5.1.0
clang++: clang version 3.7.0 (tags/RELEASE_370/final)
cl: 18.00.40629(Visual Studio 2013)
On my machine all of the commands above worked well. g++
and clang++
gave very warm warnings. cl
just quietly passed everything. But none of them threw an error. Maybe the problem lies in the compiler version?
Hope the info above can help you.
from cpp-primer.
@chihyang Thanks for your reply. I guess the problem maybe lies in the compiler version. After changing
static_cast<void*>(cs)
to static_cast<const void*>(cs)
, the compile error was disappeared.
Another question, I saw you converted the const char *
to void *
, then cout
it
would print the the address of the element. I am confused that why not use address-of operator (&)
?. And I think static_cast<void*>(cs)
will generate an anonymous object, why its address could indicate the original element(cs
)'s address?
I did a test as below:
const char* test = "test it";
void *p = &test;
const auto &refer = test;
cout << test << "===" << refer << endl;
cout << static_cast<const void*>(test) << "\t" << &test << '\t' << p << endl;
cout << static_cast<const void*>(refer) << "\t" << &refer << endl;
output(Based on g++ 5.4.0
, simial to clang++ 3.8.0
) :
test it===test it
0x401d08 0x7ffddcad4a40 0x7ffddcad4a40
0x401d08 0x7ffddcad4a40
from cpp-primer.
Hi, @chihyang . Thanks for your detailed explanation. I think I did not realize The real value of an element in vector<const char*> is an address value
(a pointer), and confused the address a pointer holds
and the address the pointer resides
.
What's more, static_cast<const void *>(cs)
should really generate an anonymous object, which is a void pointer to the same object cs
point to. So cout << static_cast<const char *>(cs)
actually print out the address cs
holds
.
Thank you again!
from cpp-primer.
Thanks a lot !! Vehry helpful.
from cpp-primer.
Hi, I'm here again :D
Exercise 10.5: In the call to equal on rosters, what would happen if both rosters held C-style strings, rather than library strings?
And the answer given is:
Answer It's the same as
std::string
But I think it is actually not the same as
std::string
.Code given:
int main() { std::vector<const char *> roster1{"Mooophy", "pezy", "Queequeg"}; std::list<const char *> roster2{"Mooophy", "pezy", "Queequeg", "shbling", "evan617"}; std::cout << std::equal(roster1.cbegin(), roster1.cend(), roster2.cbegin()); }
As we know, c-style strings cannot be compared using
==
and<
and>
, 'casue these relational operators compare addresses in pointers rather than strings represented by char pointers.
Here is the problem for this conclusion. I disagree the compiler compares address rather than strings. Simply change the code to std::cout << std::equal(roster2.cbegin(), roster2.cend(), roster1.cbegin());
, you will get 0.
For the original example, it outputs 1 because compiler assumes the first vector is as long as the second one(it doesn't check the length for you), which means only when the 2nd one is shorter, you can get a right answer.
from cpp-primer.
I learned a few things from this. thanks a lot !
from cpp-primer.
Related Issues (20)
- exercise12.8 memory leakage reason?
- Got this issue
- Typo in exercise 15.34 / 15.36
- Typo in exercise 16.36
- Cpp primer answer
- Access to private member
- Cannot understand exercise 9.52, please help. HOT 1
- ex13.44 about size and length function HOT 1
- D HOT 1
- ex2.5 notation vs type? HOT 1
- Spelling error in "Exercise 4.7" HOT 1
- Spelling error in Exercise 4.14 HOT 1
- Spelling error in Exercise 4.28 HOT 1
- "Include" error in ex15.4.5.6
- Cpp
- Ch 16 - some further reading for ex65 and 66
- A issue made by mistake.
- Ex 14.28 problem
- Ex13.42 HOT 1
- Exercise 10_32.cc (G++ giving error on the accumulate algorithm)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cpp-primer.