-7

What is the difference between . and -> when used in array? That is:

(*foo[i]).bar

vs

foo[i]->bar

or: Are they just the same?

Edit: BTW, the other reference only asked between foo.bar and foo->bar. And I know the difference. But lately, I am reading some sample that uses (*foo).bar when I thought it should have been foo->bar.

halfer
  • 19,824
  • 17
  • 99
  • 186
ReignBough
  • 435
  • 4
  • 10
  • 16
    Not again! ......... – Mitch Wheat Jul 04 '13 at 05:04
  • 5
    In sane code, it is the same. But for user defined types in C++, you can define both `->` and `*` operators, and these can do different things. I have actually seen that in "production" code. – juanchopanza Jul 04 '13 at 05:06
  • (I know that question is about objective C, but the answer is the same for C and C++) – Timothy Jones Jul 04 '13 at 05:07
  • 8
    What makes you think arrays change what those operators mean? – Rob Kennedy Jul 04 '13 at 05:08
  • @TimothyJones Only if you understand all of the Objective-C surrounding it. And it can definitely be different for C++ considering operator overloading. – Captain Obvlious Jul 04 '13 at 05:12
  • @CaptainObvlious: That's a fair comment. The C specific question is definitely a better duplicate. – Timothy Jones Jul 04 '13 at 05:15
  • @CaptainObvlious I haven't been able to find a C++ duplicate. Is there one? Neither of these marked duplicates mention operator overloading. Perhaps this should become the C++ question? – Timothy Jones Jul 04 '13 at 05:19
  • @CaptainObvlious I am voting to reopen, since the duplicates do not deal with C++, where the two code samples in the question can actually mean something different. – juanchopanza Jul 04 '13 at 05:20
  • Note that your selected answer is not fully accurate in C++, for reasons I have laid out in comments. – juanchopanza Jul 04 '13 at 05:21
  • @juanchopanza if you contribute a C++ answer expanding on your comment, I will absolutely vote for it. – Timothy Jones Jul 04 '13 at 05:22
  • @juanchopanza Same here. Neither of the specified duplicates address this question. – Captain Obvlious Jul 04 '13 at 05:25
  • 2
    @TimothyJones if this gets reopened, I will add some example code showing what I mean. – juanchopanza Jul 04 '13 at 05:44
  • 3
    Reopening is a waste of time since, for the OP's purposes, `(*foo)[i].bar` means the same as `foo[i]->bar`, notwithstanding the fact that, in C++, they can differ. – Jim Balter Jul 04 '13 at 06:02
  • Also, this is a duplicate: http://stackoverflow.com/questions/17227872/arrow-vs-dot-syntax ... if you want to expand on the C++ operator overload issues, do it there. – Jim Balter Jul 04 '13 at 06:03
  • Or rather, this is a duplicate, and operator overloading is already mentioned there: http://stackoverflow.com/questions/1238613/what-is-the-difference-between-the-dot-operator-and-in-c ... so, What @MitchWheat said. – Jim Balter Jul 04 '13 at 06:06
  • `(*foo)[i].bar` does not make sense in the context of the question about this equivalence. It should be `(*foo[i]).bar`. – AnT stands with Russia Jul 04 '13 at 07:32
  • @AndreyT it can make sense if foo is a multidimensional array. – greatwolf Jul 04 '13 at 08:15
  • @greatwolf: Yes, it is possible to declare `foo` so that the first variant will compile, no argument about that. When I say "does not make sense" I mean that it does not make sense specifically in the context of this question about the *equivalence* of the two versions. They are obviously non-equivalent and cannot be equivalent regardless of how you declare `foo`. – AnT stands with Russia Jul 04 '13 at 08:38
  • @AndreyT Yes, it may be obvious to us but it's clear that the OP is having trouble distinguishing the difference in the example he gave. I think it's worth reopening the question so an answer can clarify that to him. – greatwolf Jul 04 '13 at 08:45
  • 5
    This question and its recent changes are under discussion at http://meta.stackexchange.com/questions/187402/this-answer-is-no-longer-consistent-with-the-current-version-of-the-question. You might want to take note @reignbough. – Bart Jul 04 '13 at 18:38
  • Without regard to the edit history, I _like_ the current question. It's obviously something that can catch people out, because there are wrong answers for it in these comments. – sh1 Jul 05 '13 at 03:46
  • @TimothyJones I added a pathological example. – juanchopanza Jul 05 '13 at 05:56
  • 1
    This question is a mess now. Why don't we community wiki the whole thing, edit the question so it has both versions of the question in it, and then edit the accepted answer so it includes both answers? – Timothy Jones Jul 05 '13 at 06:55
  • @sh1 Perhaps thats true, but there was nothing stopping it being a good **new** question – Richard Tingle Jul 05 '13 at 07:29

4 Answers4

9

Assuming foo is a simple POD user-defined type used in an array, those 2 statements are certainly not the same. As you may know, all the following has the same semantic meaning for the above context:

  *foo
  *(foo + 0)
  foo[0]
  0[foo]

If you take the 2 statements and substitute them with the 3rd form you get:

(*foo)[i].bar ==> foo[0][i].bar

vs

foo[i]->bar ==> (*foo[i]).bar ==> foo[i][0].bar

You can confirm this with a simple test:

#include <stdio.h>
#include <assert.h>

struct foo_t
{
  int bar;
};

int main()
{
    foo_t foo[2][2] = { { {0xdeadbeef}, {0xbadbeef} }, 
                        { {0xbadf00d}, {0xdecafbad} } };

    assert((*foo)[1].bar == foo[0][1].bar);
    assert(foo[1]->bar == foo[1][0].bar);
    assert(foo[1]->bar != (*foo)[1].bar);

    printf("(*foo)[1].bar: %x\n", (*foo)[1].bar);
    printf("foo[1]->bar: %x\n", foo[1]->bar);
}

If they were the same, the 3rd assertion would have failed and the output would not be what it is.

greatwolf
  • 20,287
  • 13
  • 71
  • 105
  • 1
    I love how thorough your answer is, not to mention it is right! In `(*foo)[1].bar`, the pointer is dereferenced first, implying `foo[0]`. Then the sub-array is accessed at element 1. Then the bar member is accessed. In `foo[1]->bar`, it is `foo[1][0].bar` accessed, which is NOT `foo[0][1].bar`. –  Jul 04 '13 at 17:39
3

There is no difference. But foo[i]->bar is more clear then using dereference operator. Especially when you will have several levels of pointers which will end up pointing to and object, using the dereference operator will make your code to hard to understand.

halfer
  • 19,824
  • 17
  • 99
  • 186
Alexandru Barbarosie
  • 2,952
  • 3
  • 24
  • 46
  • I'm not sure about the wording in this answer. I agree that `->` is clearer, but it is still dereferencing the pointer. – Timothy Jones Jul 04 '13 at 05:09
  • 4
    In C++, there could unfortunately be a difference depending on the type of the elements of `foo`. – juanchopanza Jul 04 '13 at 05:11
  • @TimothyJones I edited the answer, now it should be more clear I think. – Alexandru Barbarosie Jul 04 '13 at 05:17
  • Sorry but this answer is inherently wrong. If `foo` is an array of type `X` where `X` provides an overload for `operator->` or `operator*()` then the semantics are different. This is significantly different than an array of pointers to type `X`. [**Live Example**](http://ideone.com/ix3QfV). – Captain Obvlious Jul 04 '13 at 05:48
  • 1
    Strictly speaking, the code in the original post is wrong. If `foo` is an array of pointers, the proper syntax for `*` operator would be `(*foo[i]).bar`, not `(*foo)[i].bar`. It is possible to properly declare `foo` for the original syntax, but in any case there will be no equivalence with `foo[i]->bar`. – AnT stands with Russia Jul 04 '13 at 07:31
  • @CaptainObvlious yes, but in the case of OP he wasn't specific on what is the type of his array, so in a way my prediction of the think which he was asking was correct. Regarding your statement: I agree with you, but in that case there are a lot of "if"s which might influence the answer. – Alexandru Barbarosie Jul 04 '13 at 08:24
  • 7
    This answer is no longer consistent with the current version of the question. – sh1 Jul 04 '13 at 13:10
  • 7
    @sh1 A question shouldn't be substantially changed to affect its meaning (even by the OP), if the question has changed it is the question and not this answer that is 'wrong'. If the OP has a new question they should ask a new question – Richard Tingle Jul 04 '13 at 18:32
  • (The question has now been rolled back to an earlier version, so I have done the same to this answer to remove the disclaimer). – halfer Dec 31 '16 at 10:32
3

First of all, the array is adding some confusion. Assuming you are asking the difference between

(*x).bar;

vs

x->bar;

for x an instance of some type T, then for pointers, the two are equivalent: both dereference a pointer to some type to access a member. But since in C++ you are allowed to overload two of the operators at play here for user defined types, namely operator->() and operator *(), you can have situations in which the two code samples are not equivalent. This should not happen in any sane code, but it is a possibility. The following code sample illustrates this:

#include <iostream>
struct Foo
{
  void hello() const { std::cout << "Foo!!!\n"; }
};

struct Bar
{
  void hello() const { std::cout << "Bar!!!\n"; }
};

struct FooBar
{
  Foo foo;
  Bar bar;
  const Foo& operator*() const { return foo; }
  const Bar* operator->() const {return &bar; }
};

int main()
{
  FooBar fb;
  fb->hello();
  (*fb).hello();
}

Output:

Bar!!!

Foo!!!

Community
  • 1
  • 1
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
1

1.-> for accessing object member variables and methods via pointer to object

Foo *foo = new Foo();
foo->var= 10;
foo->func();

2.. for accessing object member variables and methods via object instance

Foo foo;
foo.var= 10;
foo.func();
Safeer
  • 184
  • 3
  • 17