Difference Between the Dot (.) Operator and -≫ in C++

C++ is there a difference between dereferencing and using dot operator, vs using the arrow operator [duplicate]

There is no difference when obj is a pointer.

If obj is an object of some class, obj->foo will call operator->() and (*obj).foo will call operator*(). You could in theory overload these to do totally different behavior, but that would be a very badly designed class.

difference between the dot operator and arrow operator by structure object variable for tree creation in c or c++ [duplicate]

The . operator expects its operand to be an expression of type struct ... or union .... The -> operator expects its operand to be an expression of type "pointer to struct ..." or "pointer to union ...".

The expression tree has type "pointer to struct Huffman", so you use the -> operator to access a member.

The expression tree[i] has type "struct Huffman"; the subscript operator implicitly dereferences the pointer (remember that a[i] is evaluated as *(a + i)), so you use the . operator to access a member.

Basically, a->b is the somewhat more readable equivalent of (*a).b.

difference between - and . operator in C language (struct) [duplicate]

a->b is short for (*a).b.

There is no difference between a->b and (*a).b. There is a difference between (*a).b and a.b, of course - which is that the * dereferences a first (which must be a pointer or an array).

When to use arrow and when dot?

The array index operator [] has a dereference built into it.

g[i] is exactly the same as *(g + i). So g[i] refers to a DOCUMENT, not a DOCUMENT * and thus you use the member access operator . instead of the pointer-to-member operator ->.

Why does the arrow (-) operator in C exist?

I'll interpret your question as two questions: 1) why -> even exists, and 2) why . does not automatically dereference the pointer. Answers to both questions have historical roots.

Why does -> even exist?

In one of the very first versions of C language (which I will refer as CRM for "C Reference Manual", which came with 6th Edition Unix in May 1975), operator -> had very exclusive meaning, not synonymous with * and . combination

The C language described by CRM was very different from the modern C in many respects. In CRM struct members implemented the global concept of byte offset, which could be added to any address value with no type restrictions. I.e. all names of all struct members had independent global meaning (and, therefore, had to be unique). For example you could declare

struct S {
int a;
int b;
};

and name a would stand for offset 0, while name b would stand for offset 2 (assuming int type of size 2 and no padding). The language required all members of all structs in the translation unit either have unique names or stand for the same offset value. E.g. in the same translation unit you could additionally declare

struct X {
int a;
int x;
};

and that would be OK, since the name a would consistently stand for offset 0. But this additional declaration

struct Y {
int b;
int a;
};

would be formally invalid, since it attempted to "redefine" a as offset 2 and b as offset 0.

And this is where the -> operator comes in. Since every struct member name had its own self-sufficient global meaning, the language supported expressions like these

int i = 5;
i->b = 42; /* Write 42 into `int` at address 7 */
100->a = 0; /* Write 0 into `int` at address 100 */

The first assignment was interpreted by the compiler as "take address 5, add offset 2 to it and assign 42 to the int value at the resultant address". I.e. the above would assign 42 to int value at address 7. Note that this use of -> did not care about the type of the expression on the left-hand side. The left hand side was interpreted as an rvalue numerical address (be it a pointer or an integer).

This sort of trickery was not possible with * and . combination. You could not do

(*i).b = 42;

since *i is already an invalid expression. The * operator, since it is separate from ., imposes more strict type requirements on its operand. To provide a capability to work around this limitation CRM introduced the -> operator, which is independent from the type of the left-hand operand.

As Keith noted in the comments, this difference between -> and *+. combination is what CRM is referring to as "relaxation of the requirement" in 7.1.8: Except for the relaxation of the requirement that E1 be of pointer type, the expression E1−>MOS is exactly equivalent to (*E1).MOS

Later, in K&R C many features originally described in CRM were significantly reworked. The idea of "struct member as global offset identifier" was completely removed. And the functionality of -> operator became fully identical to the functionality of * and . combination.

Why can't . dereference the pointer automatically?

Again, in CRM version of the language the left operand of the . operator was required to be an lvalue. That was the only requirement imposed on that operand (and that's what made it different from ->, as explained above). Note that CRM did not require the left operand of . to have a struct type. It just required it to be an lvalue, any lvalue. This means that in CRM version of C you could write code like this

struct S { int a, b; };
struct T { float x, y, z; };

struct T c;
c.b = 55;

In this case the compiler would write 55 into an int value positioned at byte-offset 2 in the continuous memory block known as c, even though type struct T had no field named b. The compiler would not care about the actual type of c at all. All it cared about is that c was an lvalue: some sort of writable memory block.

Now note that if you did this

S *s;
...
s.b = 42;

the code would be considered valid (since s is also an lvalue) and the compiler would simply attempt to write data into the pointer s itself, at byte-offset 2. Needless to say, things like this could easily result in memory overrun, but the language did not concern itself with such matters.

I.e. in that version of the language your proposed idea about overloading operator . for pointer types would not work: operator . already had very specific meaning when used with pointers (with lvalue pointers or with any lvalues at all). It was very weird functionality, no doubt. But it was there at the time.

Of course, this weird functionality is not a very strong reason against introducing overloaded . operator for pointers (as you suggested) in the reworked version of C - K&R C. But it hasn't been done. Maybe at that time there was some legacy code written in CRM version of C that had to be supported.

(The URL for the 1975 C Reference Manual may not be stable. Another copy, possibly with some subtle differences, is here.)

Dot (.) operator and arrow (-) operator use in C vs. Objective-C

frac is actually not the same in both programs.

A C Fraction is a struct, which is a base type with no overloaded operators and is only really able to be constructed and destructed by default. If you define functions or fields on the struct, the way to access those properties in C is with the dot (.) operator. Objective-C maintains this operator when you use structs. For convenience, you can perform a dereference-and-dot operation using the arrow (->) operator (the two equivalent expressions you mention). Objective-C also preserves this when accessing structs.

An Objective-C Fraction in your example, however, is probably (one would assume) a pointer of at least type id, which is simply a classname and pointer to the instance of that class under the hood. It's also very likely to be a subclass of NSObject or NSProxy. These Objective-C classes are special in that they have a whole layer of predefined operations on top of just a C struct (if you really want to dig into it then you can take a look at the Objective-C Runtime Reference). Also important to note, an Objective-C class is always a pointer.

One of the most basic operations is objc_msgSend. When we operate on these types of objects, the Objective-C compiler interprets a dot (.) operator or the square bracket syntax ([object method]) as an objc_msgSend method call. For more detailed info about what actually happens here, see this series of posts by Bill Bumgarner, an Apple engineer who oversees the development of the Obj-C runtime.

The arrow (->) operator is not really supposed to be used on Objective-C objects. Like I said, Objective-C class instances are a C struct with an extra layer of communication added, but that layer of communication is essentially bypassed when you use the arrow. For example, if you open up Xcode and type in [UIApplication sharedApplication]-> and then bring up the method completion list, you see this:

A list of internal ivars on an Obj-C object when using the arrow operator

Here you can see a bunch of normal fields which we generally access with square bracket syntax (like [[UIApplication sharedApplication] delegate]). These particular items, however, are the C fields that store the values of their respective Objective-C properties.

So, you can roughly think of it like this:

Dot operator on a C object

  1. (at run time) Return value of the field

Arrow operator on a C object (pointer)

  1. Dereference pointer
  2. Return value of the field

Dot operator/square brackets on an Objective-C object (pointer)

  1. (at compile time) Replace with call to objc_msgSend
  2. (at run time) Look up Obj-C class definition, throw exception if something went wrong
  3. Dereference pointer
  4. Return value of the field

Arrow operator on an Objective-C object (pointer)

  1. (at run time) Dereference pointer
  2. Return value of the field

Now I'm definitely oversimplifying here, but to summarise: the arrow operators appear to do basically the same thing in both cases, but the dot operator has an extra/different meaning in Objective-C.

whats the difference between dot operator and scope resolution operator

The former (dot, .) is used to access members of an object, the latter (double colon, ::) is used to access members of a namespace or a class.

Consider the following setup.

namespace ns {
struct type
{
int var;
};
}

In this case, to refer to the structure, which is a member of a namespace, you use ::. To access the variable in an object of type type, you use ..

ns::type obj;
obj.var = 1;

(-) arrow operator and (.) dot operator , class pointer

you should read about difference between pointers and reference that might help you understand your problem.

In short, the difference is:

when you declare myclass *p it's a pointer and you can access it's members with ->, because p points to memory location.

But as soon as you call p=new myclass[10]; p starts to point to array and when you call p[n] you get a reference, which members must be accessed using ..

But if you use p->member = smth that would be the same as if you called p[0].member = smth, because number in [] is an offset from p to where search for the next array member, for example (p + 5)->member = smth would be same as p[5].member = smth



Related Topics



Leave a reply



Submit