Git Product home page Git Product logo

Comments (13)

chihyang avatar chihyang commented on June 6, 2024 5

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.

chihyang avatar chihyang commented on June 6, 2024 1

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.

lanyiyrt avatar lanyiyrt commented on June 6, 2024 1

thanks !!

from cpp-primer.

pezy avatar pezy commented on June 6, 2024

@CyberLuc I couldn't agree more. 👍

from cpp-primer.

Mooophy avatar Mooophy commented on June 6, 2024

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.

@CyberLuc @pezy

from cpp-primer.

CyberLuc avatar CyberLuc commented on June 6, 2024

Thank you for your praise! 😄

And yeah, the updated answer is good! 👍

@Mooophy

from cpp-primer.

Zjianglin avatar Zjianglin commented on June 6, 2024

@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.

chihyang avatar chihyang commented on June 6, 2024

@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.

Zjianglin avatar Zjianglin commented on June 6, 2024

@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.

Zjianglin avatar Zjianglin commented on June 6, 2024

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.

swahpy avatar swahpy commented on June 6, 2024

Thanks a lot !! Vehry helpful.

from cpp-primer.

hy-zhao23 avatar hy-zhao23 commented on June 6, 2024

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.

YacineDeghaies avatar YacineDeghaies commented on June 6, 2024

I learned a few things from this. thanks a lot !

from cpp-primer.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.