What's the difference between &C::c and &(C::c)?

Multi tool use
Multi tool use

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
8
down vote

favorite












Test code in below and I put the output info in comment.
I was using gcc 4.8.5 and Centos7.2.



#include <iostream>
#include <cstdio>

class C

public:
void foo()
printf("%p, %pn", &C::c, &(C::c)); // output value is 0x4, 0x7ffc2e7f52e8
std::cout << &C::c << std::endl; // output value is 1

int a;
int c;
;

int main(void)

C co;

printf("%pn", &C::c); // output value is 0x4
std::cout << &C::c << std::endl; // output value is 1

// printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'

co.foo();

return 0;



  1. According to C++ operator Precedence,:: operator have higher precedence than & operator. I think &C::c is equal to &(C::c), but the output says no. Why are they different?


  2. &(C::c) causes compile error in main but not in foo function,why is that?

  3. The value of &C::c is different in printf and std::cout, why is that?









share|improve this question























  • You cannot printf a pointer to member value. %p is for regular pointers only.
    – n.m.
    2 hours ago






  • 1




    @n.m. Even worse, %p is for void * only.
    – melpomene
    2 hours ago














up vote
8
down vote

favorite












Test code in below and I put the output info in comment.
I was using gcc 4.8.5 and Centos7.2.



#include <iostream>
#include <cstdio>

class C

public:
void foo()
printf("%p, %pn", &C::c, &(C::c)); // output value is 0x4, 0x7ffc2e7f52e8
std::cout << &C::c << std::endl; // output value is 1

int a;
int c;
;

int main(void)

C co;

printf("%pn", &C::c); // output value is 0x4
std::cout << &C::c << std::endl; // output value is 1

// printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'

co.foo();

return 0;



  1. According to C++ operator Precedence,:: operator have higher precedence than & operator. I think &C::c is equal to &(C::c), but the output says no. Why are they different?


  2. &(C::c) causes compile error in main but not in foo function,why is that?

  3. The value of &C::c is different in printf and std::cout, why is that?









share|improve this question























  • You cannot printf a pointer to member value. %p is for regular pointers only.
    – n.m.
    2 hours ago






  • 1




    @n.m. Even worse, %p is for void * only.
    – melpomene
    2 hours ago












up vote
8
down vote

favorite









up vote
8
down vote

favorite











Test code in below and I put the output info in comment.
I was using gcc 4.8.5 and Centos7.2.



#include <iostream>
#include <cstdio>

class C

public:
void foo()
printf("%p, %pn", &C::c, &(C::c)); // output value is 0x4, 0x7ffc2e7f52e8
std::cout << &C::c << std::endl; // output value is 1

int a;
int c;
;

int main(void)

C co;

printf("%pn", &C::c); // output value is 0x4
std::cout << &C::c << std::endl; // output value is 1

// printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'

co.foo();

return 0;



  1. According to C++ operator Precedence,:: operator have higher precedence than & operator. I think &C::c is equal to &(C::c), but the output says no. Why are they different?


  2. &(C::c) causes compile error in main but not in foo function,why is that?

  3. The value of &C::c is different in printf and std::cout, why is that?









share|improve this question















Test code in below and I put the output info in comment.
I was using gcc 4.8.5 and Centos7.2.



#include <iostream>
#include <cstdio>

class C

public:
void foo()
printf("%p, %pn", &C::c, &(C::c)); // output value is 0x4, 0x7ffc2e7f52e8
std::cout << &C::c << std::endl; // output value is 1

int a;
int c;
;

int main(void)

C co;

printf("%pn", &C::c); // output value is 0x4
std::cout << &C::c << std::endl; // output value is 1

// printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'

co.foo();

return 0;



  1. According to C++ operator Precedence,:: operator have higher precedence than & operator. I think &C::c is equal to &(C::c), but the output says no. Why are they different?


  2. &(C::c) causes compile error in main but not in foo function,why is that?

  3. The value of &C::c is different in printf and std::cout, why is that?






c++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 1 hour ago









melpomene

54.1k54084




54.1k54084










asked 3 hours ago









Xianggang ZENG

483




483











  • You cannot printf a pointer to member value. %p is for regular pointers only.
    – n.m.
    2 hours ago






  • 1




    @n.m. Even worse, %p is for void * only.
    – melpomene
    2 hours ago
















  • You cannot printf a pointer to member value. %p is for regular pointers only.
    – n.m.
    2 hours ago






  • 1




    @n.m. Even worse, %p is for void * only.
    – melpomene
    2 hours ago















You cannot printf a pointer to member value. %p is for regular pointers only.
– n.m.
2 hours ago




You cannot printf a pointer to member value. %p is for regular pointers only.
– n.m.
2 hours ago




1




1




@n.m. Even worse, %p is for void * only.
– melpomene
2 hours ago




@n.m. Even worse, %p is for void * only.
– melpomene
2 hours ago












4 Answers
4






active

oldest

votes

















up vote
5
down vote



accepted










C++ distinguishes two forms of operands to the & operator, lvalues in general and (qualified) identifiers specifically. In &C::c the operand of & is a qualified identifier (i.e. just a name) whereas in &(C::c) the operand is a general expression (because ( cannot be part of a name).



The qualified identifier form has a special case: If it refers to a non-static member of a class (like your C::c), & returns a special value known as a "pointer to member of C". See here for more information about member pointers.



In &(C::c) there is no special case. C::c is resolved normally and fails because there is no object to get a c member of. At least that's what happens in main; in methods of C (like your foo) there is an implicit this object, so C::c actually means this->c there.



As for why the output is different for printf vs. cout: When you try to print a member pointer with <<, it is implicitly converted to a bool, yielding false if it's a null pointer and true otherwise. false is printed as 0; true is printed as 1. Your member pointer is not null, so you get 1. This is different from normal pointers, which are implicitly converted to void * and printed as addresses, but member pointers cannot be converted to void * so the only applicable overload of operator<< is the one for bool. See https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt#Notes.



Note that technically your printf calls have undefined behavior. %p takes a void * and you're passing it pointers of different types. In normal function calls the automatic conversion from T * to void * would kick in, but printf is a variable-arguments function that provides no type context to its argument list, so you need a manual conversion:



printf("%pn", static_cast<void *>(&(C::c)));



The relevant part of the standard is [expr.unary.op], saying:




The result of the unary & operator is a pointer to its operand.
The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m.
Otherwise, if the type of the expression is T, the result has type “pointer to T” [...]







share|improve this answer






















  • @M.M Not if you do it in foo. See the rest of my answer.
    – melpomene
    1 hour ago










  • ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
    – Xianggang ZENG
    1 hour ago










  • @XianggangZENG Thanks, edited.
    – melpomene
    1 hour ago










  • @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
    – melpomene
    1 hour ago










  • @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
    – melpomene
    1 hour ago

















up vote
1
down vote













While the expression &C::c result in a pointer to member c the expression &(C::c) yield the address of the member variable c. The difference you're seeing in the output is that std::cout involve a bool implicit conversion that tells you whether the pointer is null or not.



Since &C::c is actually not null is implicitly converted to bool with value true or 1






share|improve this answer





























    up vote
    0
    down vote













    First, you can not access the int c by using &(C::c) outside a class. &(C::c) means the memory address of "c of instance C", somewhat &(this->c) here. However your c is not a static member of class C and there is no C instance. You can not access int x = C::c outside, either.



    So you see an error with:



    // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'


    If you have a static int c, then C::c outside the class is OK, because no instance is needed here.



    And let's run



    #include <iostream>
    #include <cstdio>

    class C

    public:
    void foo()
    printf("%p, %p, this=%pn", &C::c, &(C::c), this);

    int a;
    int c;
    ;

    int main(void)

    C co;
    co.foo();
    return 0;



    The output is:



    0x4, 0x7ffee78e47f4, this=0x7ffee78e47f0
    // 0x4 + this == 0x7ffee78e47f4
    // see reference


    And for std::out: the << &C::c is implicit-casted to bool, so true is 1 you saw. You can treat &C::c as an offset of c in C, it is unusable without a C instance.



    That's all.



    Some reference: C++: Pointer to class data member "::*"



    Full description: https://en.cppreference.com/w/cpp/language/pointer






    share|improve this answer






















    • In C::c, the C can only be a class or namespace name (never an instance)
      – M.M
      1 hour ago

















    up vote
    -2
    down vote













    Q1: There is special meaning to the syntax of & followed by an unparenthesized qualified-id. It means to form a pointer-to-member. Furthermore, there is no other way to form a pointer-to-member.



    Note: The section C++17 [expr.prim.paren]/1 says that redundant parentheses can be inserted around any expression "except otherwise indicated", however this situation seems to be intended as "otherwise indicated".




    Q3: In both cases where you write printf("%pn", &C::c);, &C::c is a pointer-to-member. The %p format specifier is only for void * so this causes undefined behaviour, and the program output is meaningless.



    The code cout << &C::c; outputs a pointer-to-member via operator<<(bool val), since there is implicit conversion from pointer-to-member to bool (with result true in all cases), see [conv.bool]/1.



    For further discussion of how to print a pointer-to-member, see this answer.




    Q2: The code &(C::c) does not form a pointer-to-member as explained above.



    Now, the code C::c is in the grammatical category id-expression. (Which is qualified-id and unqualified-id). An id-expression has some restrictions on its use, [expr.prim.id]/1:




    An id-expression that denotes a non-static data member or non-static member function of a class can only be used:



    • as part of a class member access in which the object expression refers to the member’s class or a class derived from that class, or

    • to form a pointer to member (7.6.2.1), or

    • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.



    When we are inside the C::foo function, the first of those bullet points applies. The code is the same as &c but with unnecessary qualification. This has type int *. You could output this with std::cout << &(C::c); which would show a memory address, the address of this->c.



    When we are in the main function , none of the three bullet points apply and therefore the &(C::c) is ill-formed.






    share|improve this answer






















    • The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
      – melpomene
      2 hours ago










    • Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
      – melpomene
      2 hours ago










    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52940237%2fwhats-the-difference-between-cc-and-cc%23new-answer', 'question_page');

    );

    Post as a guest






























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    5
    down vote



    accepted










    C++ distinguishes two forms of operands to the & operator, lvalues in general and (qualified) identifiers specifically. In &C::c the operand of & is a qualified identifier (i.e. just a name) whereas in &(C::c) the operand is a general expression (because ( cannot be part of a name).



    The qualified identifier form has a special case: If it refers to a non-static member of a class (like your C::c), & returns a special value known as a "pointer to member of C". See here for more information about member pointers.



    In &(C::c) there is no special case. C::c is resolved normally and fails because there is no object to get a c member of. At least that's what happens in main; in methods of C (like your foo) there is an implicit this object, so C::c actually means this->c there.



    As for why the output is different for printf vs. cout: When you try to print a member pointer with <<, it is implicitly converted to a bool, yielding false if it's a null pointer and true otherwise. false is printed as 0; true is printed as 1. Your member pointer is not null, so you get 1. This is different from normal pointers, which are implicitly converted to void * and printed as addresses, but member pointers cannot be converted to void * so the only applicable overload of operator<< is the one for bool. See https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt#Notes.



    Note that technically your printf calls have undefined behavior. %p takes a void * and you're passing it pointers of different types. In normal function calls the automatic conversion from T * to void * would kick in, but printf is a variable-arguments function that provides no type context to its argument list, so you need a manual conversion:



    printf("%pn", static_cast<void *>(&(C::c)));



    The relevant part of the standard is [expr.unary.op], saying:




    The result of the unary & operator is a pointer to its operand.
    The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m.
    Otherwise, if the type of the expression is T, the result has type “pointer to T” [...]







    share|improve this answer






















    • @M.M Not if you do it in foo. See the rest of my answer.
      – melpomene
      1 hour ago










    • ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
      – Xianggang ZENG
      1 hour ago










    • @XianggangZENG Thanks, edited.
      – melpomene
      1 hour ago










    • @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
      – melpomene
      1 hour ago










    • @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
      – melpomene
      1 hour ago














    up vote
    5
    down vote



    accepted










    C++ distinguishes two forms of operands to the & operator, lvalues in general and (qualified) identifiers specifically. In &C::c the operand of & is a qualified identifier (i.e. just a name) whereas in &(C::c) the operand is a general expression (because ( cannot be part of a name).



    The qualified identifier form has a special case: If it refers to a non-static member of a class (like your C::c), & returns a special value known as a "pointer to member of C". See here for more information about member pointers.



    In &(C::c) there is no special case. C::c is resolved normally and fails because there is no object to get a c member of. At least that's what happens in main; in methods of C (like your foo) there is an implicit this object, so C::c actually means this->c there.



    As for why the output is different for printf vs. cout: When you try to print a member pointer with <<, it is implicitly converted to a bool, yielding false if it's a null pointer and true otherwise. false is printed as 0; true is printed as 1. Your member pointer is not null, so you get 1. This is different from normal pointers, which are implicitly converted to void * and printed as addresses, but member pointers cannot be converted to void * so the only applicable overload of operator<< is the one for bool. See https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt#Notes.



    Note that technically your printf calls have undefined behavior. %p takes a void * and you're passing it pointers of different types. In normal function calls the automatic conversion from T * to void * would kick in, but printf is a variable-arguments function that provides no type context to its argument list, so you need a manual conversion:



    printf("%pn", static_cast<void *>(&(C::c)));



    The relevant part of the standard is [expr.unary.op], saying:




    The result of the unary & operator is a pointer to its operand.
    The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m.
    Otherwise, if the type of the expression is T, the result has type “pointer to T” [...]







    share|improve this answer






















    • @M.M Not if you do it in foo. See the rest of my answer.
      – melpomene
      1 hour ago










    • ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
      – Xianggang ZENG
      1 hour ago










    • @XianggangZENG Thanks, edited.
      – melpomene
      1 hour ago










    • @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
      – melpomene
      1 hour ago










    • @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
      – melpomene
      1 hour ago












    up vote
    5
    down vote



    accepted







    up vote
    5
    down vote



    accepted






    C++ distinguishes two forms of operands to the & operator, lvalues in general and (qualified) identifiers specifically. In &C::c the operand of & is a qualified identifier (i.e. just a name) whereas in &(C::c) the operand is a general expression (because ( cannot be part of a name).



    The qualified identifier form has a special case: If it refers to a non-static member of a class (like your C::c), & returns a special value known as a "pointer to member of C". See here for more information about member pointers.



    In &(C::c) there is no special case. C::c is resolved normally and fails because there is no object to get a c member of. At least that's what happens in main; in methods of C (like your foo) there is an implicit this object, so C::c actually means this->c there.



    As for why the output is different for printf vs. cout: When you try to print a member pointer with <<, it is implicitly converted to a bool, yielding false if it's a null pointer and true otherwise. false is printed as 0; true is printed as 1. Your member pointer is not null, so you get 1. This is different from normal pointers, which are implicitly converted to void * and printed as addresses, but member pointers cannot be converted to void * so the only applicable overload of operator<< is the one for bool. See https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt#Notes.



    Note that technically your printf calls have undefined behavior. %p takes a void * and you're passing it pointers of different types. In normal function calls the automatic conversion from T * to void * would kick in, but printf is a variable-arguments function that provides no type context to its argument list, so you need a manual conversion:



    printf("%pn", static_cast<void *>(&(C::c)));



    The relevant part of the standard is [expr.unary.op], saying:




    The result of the unary & operator is a pointer to its operand.
    The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m.
    Otherwise, if the type of the expression is T, the result has type “pointer to T” [...]







    share|improve this answer














    C++ distinguishes two forms of operands to the & operator, lvalues in general and (qualified) identifiers specifically. In &C::c the operand of & is a qualified identifier (i.e. just a name) whereas in &(C::c) the operand is a general expression (because ( cannot be part of a name).



    The qualified identifier form has a special case: If it refers to a non-static member of a class (like your C::c), & returns a special value known as a "pointer to member of C". See here for more information about member pointers.



    In &(C::c) there is no special case. C::c is resolved normally and fails because there is no object to get a c member of. At least that's what happens in main; in methods of C (like your foo) there is an implicit this object, so C::c actually means this->c there.



    As for why the output is different for printf vs. cout: When you try to print a member pointer with <<, it is implicitly converted to a bool, yielding false if it's a null pointer and true otherwise. false is printed as 0; true is printed as 1. Your member pointer is not null, so you get 1. This is different from normal pointers, which are implicitly converted to void * and printed as addresses, but member pointers cannot be converted to void * so the only applicable overload of operator<< is the one for bool. See https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt#Notes.



    Note that technically your printf calls have undefined behavior. %p takes a void * and you're passing it pointers of different types. In normal function calls the automatic conversion from T * to void * would kick in, but printf is a variable-arguments function that provides no type context to its argument list, so you need a manual conversion:



    printf("%pn", static_cast<void *>(&(C::c)));



    The relevant part of the standard is [expr.unary.op], saying:




    The result of the unary & operator is a pointer to its operand.
    The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m.
    Otherwise, if the type of the expression is T, the result has type “pointer to T” [...]








    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 1 hour ago

























    answered 2 hours ago









    melpomene

    54.1k54084




    54.1k54084











    • @M.M Not if you do it in foo. See the rest of my answer.
      – melpomene
      1 hour ago










    • ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
      – Xianggang ZENG
      1 hour ago










    • @XianggangZENG Thanks, edited.
      – melpomene
      1 hour ago










    • @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
      – melpomene
      1 hour ago










    • @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
      – melpomene
      1 hour ago
















    • @M.M Not if you do it in foo. See the rest of my answer.
      – melpomene
      1 hour ago










    • ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
      – Xianggang ZENG
      1 hour ago










    • @XianggangZENG Thanks, edited.
      – melpomene
      1 hour ago










    • @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
      – melpomene
      1 hour ago










    • @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
      – melpomene
      1 hour ago















    @M.M Not if you do it in foo. See the rest of my answer.
    – melpomene
    1 hour ago




    @M.M Not if you do it in foo. See the rest of my answer.
    – melpomene
    1 hour ago












    ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
    – Xianggang ZENG
    1 hour ago




    ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
    – Xianggang ZENG
    1 hour ago












    @XianggangZENG Thanks, edited.
    – melpomene
    1 hour ago




    @XianggangZENG Thanks, edited.
    – melpomene
    1 hour ago












    @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
    – melpomene
    1 hour ago




    @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
    – melpomene
    1 hour ago












    @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
    – melpomene
    1 hour ago




    @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
    – melpomene
    1 hour ago












    up vote
    1
    down vote













    While the expression &C::c result in a pointer to member c the expression &(C::c) yield the address of the member variable c. The difference you're seeing in the output is that std::cout involve a bool implicit conversion that tells you whether the pointer is null or not.



    Since &C::c is actually not null is implicitly converted to bool with value true or 1






    share|improve this answer


























      up vote
      1
      down vote













      While the expression &C::c result in a pointer to member c the expression &(C::c) yield the address of the member variable c. The difference you're seeing in the output is that std::cout involve a bool implicit conversion that tells you whether the pointer is null or not.



      Since &C::c is actually not null is implicitly converted to bool with value true or 1






      share|improve this answer
























        up vote
        1
        down vote










        up vote
        1
        down vote









        While the expression &C::c result in a pointer to member c the expression &(C::c) yield the address of the member variable c. The difference you're seeing in the output is that std::cout involve a bool implicit conversion that tells you whether the pointer is null or not.



        Since &C::c is actually not null is implicitly converted to bool with value true or 1






        share|improve this answer














        While the expression &C::c result in a pointer to member c the expression &(C::c) yield the address of the member variable c. The difference you're seeing in the output is that std::cout involve a bool implicit conversion that tells you whether the pointer is null or not.



        Since &C::c is actually not null is implicitly converted to bool with value true or 1







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 2 hours ago

























        answered 2 hours ago









        Jans

        5,01111926




        5,01111926




















            up vote
            0
            down vote













            First, you can not access the int c by using &(C::c) outside a class. &(C::c) means the memory address of "c of instance C", somewhat &(this->c) here. However your c is not a static member of class C and there is no C instance. You can not access int x = C::c outside, either.



            So you see an error with:



            // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'


            If you have a static int c, then C::c outside the class is OK, because no instance is needed here.



            And let's run



            #include <iostream>
            #include <cstdio>

            class C

            public:
            void foo()
            printf("%p, %p, this=%pn", &C::c, &(C::c), this);

            int a;
            int c;
            ;

            int main(void)

            C co;
            co.foo();
            return 0;



            The output is:



            0x4, 0x7ffee78e47f4, this=0x7ffee78e47f0
            // 0x4 + this == 0x7ffee78e47f4
            // see reference


            And for std::out: the << &C::c is implicit-casted to bool, so true is 1 you saw. You can treat &C::c as an offset of c in C, it is unusable without a C instance.



            That's all.



            Some reference: C++: Pointer to class data member "::*"



            Full description: https://en.cppreference.com/w/cpp/language/pointer






            share|improve this answer






















            • In C::c, the C can only be a class or namespace name (never an instance)
              – M.M
              1 hour ago














            up vote
            0
            down vote













            First, you can not access the int c by using &(C::c) outside a class. &(C::c) means the memory address of "c of instance C", somewhat &(this->c) here. However your c is not a static member of class C and there is no C instance. You can not access int x = C::c outside, either.



            So you see an error with:



            // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'


            If you have a static int c, then C::c outside the class is OK, because no instance is needed here.



            And let's run



            #include <iostream>
            #include <cstdio>

            class C

            public:
            void foo()
            printf("%p, %p, this=%pn", &C::c, &(C::c), this);

            int a;
            int c;
            ;

            int main(void)

            C co;
            co.foo();
            return 0;



            The output is:



            0x4, 0x7ffee78e47f4, this=0x7ffee78e47f0
            // 0x4 + this == 0x7ffee78e47f4
            // see reference


            And for std::out: the << &C::c is implicit-casted to bool, so true is 1 you saw. You can treat &C::c as an offset of c in C, it is unusable without a C instance.



            That's all.



            Some reference: C++: Pointer to class data member "::*"



            Full description: https://en.cppreference.com/w/cpp/language/pointer






            share|improve this answer






















            • In C::c, the C can only be a class or namespace name (never an instance)
              – M.M
              1 hour ago












            up vote
            0
            down vote










            up vote
            0
            down vote









            First, you can not access the int c by using &(C::c) outside a class. &(C::c) means the memory address of "c of instance C", somewhat &(this->c) here. However your c is not a static member of class C and there is no C instance. You can not access int x = C::c outside, either.



            So you see an error with:



            // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'


            If you have a static int c, then C::c outside the class is OK, because no instance is needed here.



            And let's run



            #include <iostream>
            #include <cstdio>

            class C

            public:
            void foo()
            printf("%p, %p, this=%pn", &C::c, &(C::c), this);

            int a;
            int c;
            ;

            int main(void)

            C co;
            co.foo();
            return 0;



            The output is:



            0x4, 0x7ffee78e47f4, this=0x7ffee78e47f0
            // 0x4 + this == 0x7ffee78e47f4
            // see reference


            And for std::out: the << &C::c is implicit-casted to bool, so true is 1 you saw. You can treat &C::c as an offset of c in C, it is unusable without a C instance.



            That's all.



            Some reference: C++: Pointer to class data member "::*"



            Full description: https://en.cppreference.com/w/cpp/language/pointer






            share|improve this answer














            First, you can not access the int c by using &(C::c) outside a class. &(C::c) means the memory address of "c of instance C", somewhat &(this->c) here. However your c is not a static member of class C and there is no C instance. You can not access int x = C::c outside, either.



            So you see an error with:



            // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'


            If you have a static int c, then C::c outside the class is OK, because no instance is needed here.



            And let's run



            #include <iostream>
            #include <cstdio>

            class C

            public:
            void foo()
            printf("%p, %p, this=%pn", &C::c, &(C::c), this);

            int a;
            int c;
            ;

            int main(void)

            C co;
            co.foo();
            return 0;



            The output is:



            0x4, 0x7ffee78e47f4, this=0x7ffee78e47f0
            // 0x4 + this == 0x7ffee78e47f4
            // see reference


            And for std::out: the << &C::c is implicit-casted to bool, so true is 1 you saw. You can treat &C::c as an offset of c in C, it is unusable without a C instance.



            That's all.



            Some reference: C++: Pointer to class data member "::*"



            Full description: https://en.cppreference.com/w/cpp/language/pointer







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 2 hours ago

























            answered 2 hours ago









            shawn

            2,420616




            2,420616











            • In C::c, the C can only be a class or namespace name (never an instance)
              – M.M
              1 hour ago
















            • In C::c, the C can only be a class or namespace name (never an instance)
              – M.M
              1 hour ago















            In C::c, the C can only be a class or namespace name (never an instance)
            – M.M
            1 hour ago




            In C::c, the C can only be a class or namespace name (never an instance)
            – M.M
            1 hour ago










            up vote
            -2
            down vote













            Q1: There is special meaning to the syntax of & followed by an unparenthesized qualified-id. It means to form a pointer-to-member. Furthermore, there is no other way to form a pointer-to-member.



            Note: The section C++17 [expr.prim.paren]/1 says that redundant parentheses can be inserted around any expression "except otherwise indicated", however this situation seems to be intended as "otherwise indicated".




            Q3: In both cases where you write printf("%pn", &C::c);, &C::c is a pointer-to-member. The %p format specifier is only for void * so this causes undefined behaviour, and the program output is meaningless.



            The code cout << &C::c; outputs a pointer-to-member via operator<<(bool val), since there is implicit conversion from pointer-to-member to bool (with result true in all cases), see [conv.bool]/1.



            For further discussion of how to print a pointer-to-member, see this answer.




            Q2: The code &(C::c) does not form a pointer-to-member as explained above.



            Now, the code C::c is in the grammatical category id-expression. (Which is qualified-id and unqualified-id). An id-expression has some restrictions on its use, [expr.prim.id]/1:




            An id-expression that denotes a non-static data member or non-static member function of a class can only be used:



            • as part of a class member access in which the object expression refers to the member’s class or a class derived from that class, or

            • to form a pointer to member (7.6.2.1), or

            • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.



            When we are inside the C::foo function, the first of those bullet points applies. The code is the same as &c but with unnecessary qualification. This has type int *. You could output this with std::cout << &(C::c); which would show a memory address, the address of this->c.



            When we are in the main function , none of the three bullet points apply and therefore the &(C::c) is ill-formed.






            share|improve this answer






















            • The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
              – melpomene
              2 hours ago










            • Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
              – melpomene
              2 hours ago














            up vote
            -2
            down vote













            Q1: There is special meaning to the syntax of & followed by an unparenthesized qualified-id. It means to form a pointer-to-member. Furthermore, there is no other way to form a pointer-to-member.



            Note: The section C++17 [expr.prim.paren]/1 says that redundant parentheses can be inserted around any expression "except otherwise indicated", however this situation seems to be intended as "otherwise indicated".




            Q3: In both cases where you write printf("%pn", &C::c);, &C::c is a pointer-to-member. The %p format specifier is only for void * so this causes undefined behaviour, and the program output is meaningless.



            The code cout << &C::c; outputs a pointer-to-member via operator<<(bool val), since there is implicit conversion from pointer-to-member to bool (with result true in all cases), see [conv.bool]/1.



            For further discussion of how to print a pointer-to-member, see this answer.




            Q2: The code &(C::c) does not form a pointer-to-member as explained above.



            Now, the code C::c is in the grammatical category id-expression. (Which is qualified-id and unqualified-id). An id-expression has some restrictions on its use, [expr.prim.id]/1:




            An id-expression that denotes a non-static data member or non-static member function of a class can only be used:



            • as part of a class member access in which the object expression refers to the member’s class or a class derived from that class, or

            • to form a pointer to member (7.6.2.1), or

            • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.



            When we are inside the C::foo function, the first of those bullet points applies. The code is the same as &c but with unnecessary qualification. This has type int *. You could output this with std::cout << &(C::c); which would show a memory address, the address of this->c.



            When we are in the main function , none of the three bullet points apply and therefore the &(C::c) is ill-formed.






            share|improve this answer






















            • The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
              – melpomene
              2 hours ago










            • Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
              – melpomene
              2 hours ago












            up vote
            -2
            down vote










            up vote
            -2
            down vote









            Q1: There is special meaning to the syntax of & followed by an unparenthesized qualified-id. It means to form a pointer-to-member. Furthermore, there is no other way to form a pointer-to-member.



            Note: The section C++17 [expr.prim.paren]/1 says that redundant parentheses can be inserted around any expression "except otherwise indicated", however this situation seems to be intended as "otherwise indicated".




            Q3: In both cases where you write printf("%pn", &C::c);, &C::c is a pointer-to-member. The %p format specifier is only for void * so this causes undefined behaviour, and the program output is meaningless.



            The code cout << &C::c; outputs a pointer-to-member via operator<<(bool val), since there is implicit conversion from pointer-to-member to bool (with result true in all cases), see [conv.bool]/1.



            For further discussion of how to print a pointer-to-member, see this answer.




            Q2: The code &(C::c) does not form a pointer-to-member as explained above.



            Now, the code C::c is in the grammatical category id-expression. (Which is qualified-id and unqualified-id). An id-expression has some restrictions on its use, [expr.prim.id]/1:




            An id-expression that denotes a non-static data member or non-static member function of a class can only be used:



            • as part of a class member access in which the object expression refers to the member’s class or a class derived from that class, or

            • to form a pointer to member (7.6.2.1), or

            • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.



            When we are inside the C::foo function, the first of those bullet points applies. The code is the same as &c but with unnecessary qualification. This has type int *. You could output this with std::cout << &(C::c); which would show a memory address, the address of this->c.



            When we are in the main function , none of the three bullet points apply and therefore the &(C::c) is ill-formed.






            share|improve this answer














            Q1: There is special meaning to the syntax of & followed by an unparenthesized qualified-id. It means to form a pointer-to-member. Furthermore, there is no other way to form a pointer-to-member.



            Note: The section C++17 [expr.prim.paren]/1 says that redundant parentheses can be inserted around any expression "except otherwise indicated", however this situation seems to be intended as "otherwise indicated".




            Q3: In both cases where you write printf("%pn", &C::c);, &C::c is a pointer-to-member. The %p format specifier is only for void * so this causes undefined behaviour, and the program output is meaningless.



            The code cout << &C::c; outputs a pointer-to-member via operator<<(bool val), since there is implicit conversion from pointer-to-member to bool (with result true in all cases), see [conv.bool]/1.



            For further discussion of how to print a pointer-to-member, see this answer.




            Q2: The code &(C::c) does not form a pointer-to-member as explained above.



            Now, the code C::c is in the grammatical category id-expression. (Which is qualified-id and unqualified-id). An id-expression has some restrictions on its use, [expr.prim.id]/1:




            An id-expression that denotes a non-static data member or non-static member function of a class can only be used:



            • as part of a class member access in which the object expression refers to the member’s class or a class derived from that class, or

            • to form a pointer to member (7.6.2.1), or

            • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.



            When we are inside the C::foo function, the first of those bullet points applies. The code is the same as &c but with unnecessary qualification. This has type int *. You could output this with std::cout << &(C::c); which would show a memory address, the address of this->c.



            When we are in the main function , none of the three bullet points apply and therefore the &(C::c) is ill-formed.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 1 hour ago

























            answered 2 hours ago









            M.M

            102k10106224




            102k10106224











            • The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
              – melpomene
              2 hours ago










            • Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
              – melpomene
              2 hours ago
















            • The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
              – melpomene
              2 hours ago










            • Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
              – melpomene
              2 hours ago















            The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
            – melpomene
            2 hours ago




            The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
            – melpomene
            2 hours ago












            Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
            – melpomene
            2 hours ago




            Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
            – melpomene
            2 hours ago

















             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52940237%2fwhats-the-difference-between-cc-and-cc%23new-answer', 'question_page');

            );

            Post as a guest













































































            I1Glo u7ePBalnwGc,lLftU8,pIrxl8jqKZUBWZ zjkS CtNN8vjg
            MJT 2n,Iq,0sXGTduc3L3ej,iSOYi

            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            How many registers does an x86_64 CPU actually have?

            Displaying single band from multi-band raster using QGIS