How do the "->" and "." member access operations differ in C - c

I have looked at some resources to tell me how -> and . are different, but they seem to do the same thing. Does -> act like a dot operator on a struct?

. is used when you have a struct, and -> is used when you have a pointer to a struct. The arrow is a short form for dereferencing the pointer and then using .: p->field is the same as (*p).field.

They are almost the same thing. The only difference is that "->" takes a pointer to a struct on the left side while "." takes a struct; "->" deferences (i.e. follows) the pointer before accessing the struct member. So,
struct foo bar;
bar.x = 0;
is the same as:
struct foo bar;
struct foo *diddly = &bar;
diddly->x = 0;

you're using a dot when accessing object's members, and the arrow -> when accessing members through the pointer to an object

-> is to a struct pointer what . is to a struct.
struct Data data;
data.content = 1;
struct Data* pData = &data;
pData->content = 2;

Ah, I just came across the same question, when looking at locale settings. One is for accessing the attributes through the pointer and one is for the dereferenced struct:
#include <locale.h>
int main (void) {
struct lconv *locale_ptr;
locale_ptr = localeconv();
printf("Currency symbol: %s\n", (*locale_ptr).currency_symbol);
}
is equivalent to:
int main (void) {
struct lconv *locale_ptr;
locale_ptr = localeconv();
printf("Currency symbol: %s\n", locale_ptr->currency_symbol);
}

[.] operates on a object of a structure. Once a object of a particular structure is declared the [.] operator can be used to directly operate with the members.
[->] operates on a pointer to the object of a structure. This is a dereference operator that is used exclusively with pointers to objects with members. Thus enabling us to access members to the object to which we have a reference.
Based of the declaration you can use these operators.

Most simply you use . when operating on a Struct itself and -> when operating on a pointer to a struct.
To show in code:
struct s myStruct;
myStruct.num = 5;
Is valid, but:
struct s myStruct;
myStruct->num = 5;
Is invalid as myStruct is not a pointer.
struct s *myStruct;
myStruct->num = 5;
Would be valid.
The -> operator is actually a shorthand for (*myStruct).num;

The C language, unlike many other languages allows variables to have objects (here structs) as values and also pointers to objects as values. Depending on which type of variable is used, "." or "->" have to be used respectively.

The operator a->b, canonically, means (*a).b .
So, unlike ".", it will dereference it's first argument.
I could be wrong on this point, but my understand is that it's not "officially" part of C (you specifically mention C in the question). It's a C++ construct that most C compiler vendors have added to C. However, I must admit that I haven't kept up with changes to C, so I could be completely wrong there.
In C++ there are further differences. The "->" operator is overloadable, where as the "." is not.

both used in C++ to access the members of a class. But
. is not overloadable,
→ is overloadable
Here's an example showing how you can use both of them:
#include<iostream>
class A {
public: int b;
A() { b = 5; }
};
int main() {
A a = A();
A* x = &a;
std::cout << "a.b = " << a.b << "\n";
std::cout << "x->b = " << x->b << "\n";
return 0;
}

Related

Is "pointer->register_next->value" the same as "pointer->register_next.value" in C?

I'm studying searching procedures in lists (C language), and I've seen procedures use both the arrow operator and the dot operator when writing conditions.
For a struct like...
struct node{
int value; //value, can be any type
struct node *next;
};
I've seen...
if(current->next->value == searched_value)
...and
if(current->next.value == searched_value)
...being used. My question is: Are are these method interchangeable in any given case? (i.e they are the same)
As #PabloSantaCruz correctly notes, accessing members of a struct using '->' and '.' are very much not the same.
To know which to use, you simply have to answer the question of "Do I have a struct or pointer to struct?"
When accessing struct members, the '->' (arrow) operator is used to dereference a pointer to struct to access the members. When dealing with a struct itself the '.' (dot) operator is used to access its members.
There is nothing better than practice and an example to help compare/contrast the usage, for example, the following declares an array of struct to serve as your list, where each element is a struct. To simply access the members of each element all that is needed is the dot operator. However, to show how they are related, if you take the address of each element, thereby creating a pointer to it, the arrow operator can be used.
#include <stdio.h>
struct node {
int val;
struct node *next;
};
int main (void) {
struct node list[2] = {{1, &list[1]}, {2, NULL}}, /* array */
*l = list; /* pointer to first element */
puts ("\nusing list, e.g. list[0].val\n"); /* the dot operator */
printf (" %d %d\n", list[0].val, list[1].val);
/* taking the address of each element and using the arrow operator */
puts ("\nusing address of each list element, e.g. (&list[0])->val\n");
printf (" %d %d\n", (&list[0])->val, (&list[1])->val);
puts ("\nusing l, e.g. l->val\n"); /* using the pointer & arrow op. */
printf (" %d %d\n", l->val, (l + 1)->val);
puts ("\ntraversing list using l\n"); /* traversing with the pointer */
while (l) {
printf (" %d", l->val);
l = l->next;
}
putchar ('\n');
}
In each case above, you simply answer the question "Do I have a struct or pointer to struct?" to know which operator to use.
Example Use/Output
$ ./bin/ll_array
using list, e.g. list[0].val
1 2
using address of each list element, e.g. (&list[0])->val
1 2
using l, e.g. l->val
1 2
traversing list using l
1 2
Look things over and let me know if you have further questions.
No. They're definitely not the same and they are not interchangeable.
The arrow operator -> only works when you have a pointer to a struct as a variable.
So:
struct *p;
p->a = 0; // correct
p.a = 0; //syntax error
Clearly you must have been looking something else, because if next is of struct node * type (a pointer to struct node) then, current->next.value is an error.
In gcc you should get an error saying: error: request for member ‘value’ in something not a structure or union
current->next->value can also be written (*(*current).next).value).
The reason you need those parenthesis is that . has higher precedence than *. The -> is basically just syntactic sugar to reduce the amount of parenthesis.
Are are these method interchangeable in any given case?
In a way yes. You can always use dots instead of arrows if you use parenthesis the proper way. You can also go the other way. This code compiles without warnings and prints 1 2 3 4.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int foo;
int bar;
} myStruct;
int main() {
myStruct a;
(&a)->foo = 1;
a.bar = 2;
myStruct * b = malloc(sizeof *b);
b->foo = 3;
(*b).bar = 4;
printf("%d %d %d %d\n", a.foo, (&a)->bar, (*b).foo, b->bar);
}
The -> operator requires the left operator to be a pointer, while . requires it to not be a pointer. But as you can see, dereferencering a pointer (using *) gives you the data the pointer is pointing at, and thus you can use . instead. And using & gives you the address of the object, which enforces the use of -> instead of ..
In practice, this should never be an issue. Choose the most convenient, and I cannot think of an example where I would not know which to choose.
Actually, this is related to the [] operator, which you are using for indexing arrays. That is also just syntactic sugar. The expression a[i] is equivalent to *(a+i). This has the funny consequence that a[i] is actually the same as i[a].

Pointers to pointers to structures

Hi have a function which takes the argument of a pointer, to a pointer to a struct. I'm having trouble accessing the members of my struct. Do struct pointers behave differently to pointers of other types, or am i just missing somethign essential?
struct mystr {
int num;
};
void fun(mystr **out) {
printf("%d",**out.num); <-- where the problem arises
}
No, 'struct pointers' (whatever you mean) work precisely the same way as pointers to other types.
You just need to recall operators precedence:
. structure member access
->structure member access through pointer
(...)
* indirection (dereference)
(...)
So your expression **out.num is interpreted as *(*(out.num)) and your (out.num) is not a pointer, hence applying an asterisk to it is an error.
You need to parenthesise appropriate part of the expression to force a non-default operators binding: (**out).num – dereference out twice first to get to a struct mystr variable, then access that variable's num member.
The -> operator serves as a shortcut for accessing a member of pointed stucture:
(ptr_expr)->member_name is equivalent to (*(ptr_expr)).member_name
so you can replace (**out).num with (*out)->num.
Possible to the solution to use this :
printf("%d",(*out)->num);
instead of
printf("%d",**out.num);
This is the way you should implement, here printf("%d",(*(*out)).num); will print 1.
#include<stdio.h>
#include<stdlib.h>
struct mystr{
int num;
};
void fun(struct mystr **out) {
printf("%d",(*(*out)).num);
}
int main()
{
struct mystr m;
struct mystr *p;
struct mystr **pp;
p=&m;
pp=&p;
m.num=1;
fun(pp);
return 0;
}
Here m is our structure, p is pointer to structure and pp is pointer to the pointer p.

Arrow Operator Usage in Linked List [duplicate]

I am reading a book called "Teach Yourself C in 21 Days" (I have already learned Java and C# so I am moving at a much faster pace). I was reading the chapter on pointers and the -> (arrow) operator came up without explanation. I think that it is used to call members and functions (like the equivalent of the . (dot) operator, but for pointers instead of members). But I am not entirely sure.
Could I please get an explanation and a code sample?
foo->bar is equivalent to (*foo).bar, i.e. it gets the member called bar from the struct that foo points to.
Yes, that's it.
It's just the dot version when you want to access elements of a struct/class that is a pointer instead of a reference.
struct foo
{
int x;
float y;
};
struct foo var;
struct foo* pvar;
pvar = malloc(sizeof(struct foo));
var.x = 5;
(&var)->y = 14.3;
pvar->y = 22.4;
(*pvar).x = 6;
That's it!
I'd just add to the answers the "why?".
. is standard member access operator that has a higher precedence than * pointer operator.
When you are trying to access a struct's internals and you wrote it as *foo.bar then the compiler would think to want a 'bar' element of 'foo' (which is an address in memory) and obviously that mere address does not have any members.
Thus you need to ask the compiler to first dereference whith (*foo) and then access the member element: (*foo).bar, which is a bit clumsy to write so the good folks have come up with a shorthand version: foo->bar which is sort of member access by pointer operator.
a->b is just short for (*a).b in every way (same for functions: a->b() is short for (*a).b()).
foo->bar is only shorthand for (*foo).bar. That's all there is to it.
Well I have to add something as well. Structure is a bit different than array because array is a pointer and structure is not. So be careful!
Lets say I write this useless piece of code:
#include <stdio.h>
typedef struct{
int km;
int kph;
int kg;
} car;
int main(void){
car audi = {12000, 230, 760};
car *ptr = &audi;
}
Here pointer ptr points to the address (!) of the structure variable audi but beside address structure also has a chunk of data (!)! The first member of the chunk of data has the same address than structure itself and you can get it's data by only dereferencing a pointer like this *ptr (no braces).
But If you want to acess any other member than the first one, you have to add a designator like .km, .kph, .kg which are nothing more than offsets to the base address of the chunk of data...
But because of the preceedence you can't write *ptr.kg as access operator . is evaluated before dereference operator * and you would get *(ptr.kg) which is not possible as pointer has no members! And compiler knows this and will therefore issue an error e.g.:
error: ‘ptr’ is a pointer; did you mean to use ‘->’?
printf("%d\n", *ptr.km);
Instead you use this (*ptr).kg and you force compiler to 1st dereference the pointer and enable acess to the chunk of data and 2nd you add an offset (designator) to choose the member.
Check this image I made:
But if you would have nested members this syntax would become unreadable and therefore -> was introduced. I think readability is the only justifiable reason for using it as this ptr->kg is much easier to write than (*ptr).kg.
Now let us write this differently so that you see the connection more clearly. (*ptr).kg ⟹ (*&audi).kg ⟹ audi.kg. Here I first used the fact that ptr is an "address of audi" i.e. &audi and fact that "reference" & and "dereference" * operators cancel eachother out.
struct Node {
int i;
int j;
};
struct Node a, *p = &a;
Here the to access the values of i and j we can use the variable a and the pointer p as follows: a.i, (*p).i and p->i are all the same.
Here . is a "Direct Selector" and -> is an "Indirect Selector".
I had to make a small change to Jack's program to get it to run. After declaring the struct pointer pvar, point it to the address of var. I found this solution on page 242 of Stephen Kochan's Programming in C.
#include <stdio.h>
int main()
{
struct foo
{
int x;
float y;
};
struct foo var;
struct foo* pvar;
pvar = &var;
var.x = 5;
(&var)->y = 14.3;
printf("%i - %.02f\n", var.x, (&var)->y);
pvar->x = 6;
pvar->y = 22.4;
printf("%i - %.02f\n", pvar->x, pvar->y);
return 0;
}
Run this in vim with the following command:
:!gcc -o var var.c && ./var
Will output:
5 - 14.30
6 - 22.40
#include<stdio.h>
int main()
{
struct foo
{
int x;
float y;
} var1;
struct foo var;
struct foo* pvar;
pvar = &var1;
/* if pvar = &var; it directly
takes values stored in var, and if give
new > values like pvar->x = 6; pvar->y = 22.4;
it modifies the values of var
object..so better to give new reference. */
var.x = 5;
(&var)->y = 14.3;
printf("%i - %.02f\n", var.x, (&var)->y);
pvar->x = 6;
pvar->y = 22.4;
printf("%i - %.02f\n", pvar->x, pvar->y);
return 0;
}
The -> operator makes the code more readable than the * operator in some situations.
Such as: (quoted from the EDK II project)
typedef
EFI_STATUS
(EFIAPI *EFI_BLOCK_READ)(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
);
struct _EFI_BLOCK_IO_PROTOCOL {
///
/// The revision to which the block IO interface adheres. All future
/// revisions must be backwards compatible. If a future version is not
/// back wards compatible, it is not the same GUID.
///
UINT64 Revision;
///
/// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
///
EFI_BLOCK_IO_MEDIA *Media;
EFI_BLOCK_RESET Reset;
EFI_BLOCK_READ ReadBlocks;
EFI_BLOCK_WRITE WriteBlocks;
EFI_BLOCK_FLUSH FlushBlocks;
};
The _EFI_BLOCK_IO_PROTOCOL struct contains 4 function pointer members.
Suppose you have a variable struct _EFI_BLOCK_IO_PROTOCOL * pStruct, and you want to use the good old * operator to call it's member function pointer. You will end up with code like this:
(*pStruct).ReadBlocks(...arguments...)
But with the -> operator, you can write like this:
pStruct->ReadBlocks(...arguments...).
Which looks better?
#include<stdio.h>
struct examp{
int number;
};
struct examp a,*b=&a;`enter code here`
main()
{
a.number=5;
/* a.number,b->number,(*b).number produces same output. b->number is mostly used in linked list*/
printf("%d \n %d \n %d",a.number,b->number,(*b).number);
}
output is 5
5 5
Dot is a dereference operator and used to connect the structure variable for a particular record of structure.
Eg :
struct student
{
int s.no;
Char name [];
int age;
} s1,s2;
main()
{
s1.name;
s2.name;
}
In such way we can use a dot operator to access the structure variable

Return a structure with const array in C

Is it safe to return a struct with array data member in C?
Something like
struct my_str {
int v[5];
};
struct my_str ret_stupid() {
struct my_str rval;
/*do something..*/
return rval;
}
I don't know why... I'm a bit puzzled. (I've tried and it does work). Is there some standard explaining how this operation actually is performed? I mean the mechanism of struct return and assignment too could be useful to understand better.
Is it safe to return a struct with array data member in C?
Yes.
struct are copied bit-wise. Bit-wise copying a struct that has an array as a member makes sure that the copy of struct has a copy of the array too.
Structures are a lot like arrays.
They can contain variables of any kind.
Their addresses will be sorted stacked as long as you leave no gaps or invoke the preprocessor directive #pragma pack
"Is it safe", depends of the code hiding there..
/do something../
But in general - yes. This is just a function of type struct my_str and has to return struct my_str
What the structure contains - doesn't matter. Still safe to use.
You can return a structure from a function without any problems. It's a well-defined part of the language. You can pass structures to functions as well - a structure is exactly the same as any built-in type for purposes of parameter passing, return values, and assignment.
Here's an example
#include <stdio.h>
int func(int x)
{
int r = x;
return r;
}
int main(void)
{
int x = 12;
int y = func(x);
printf("%d\n", y);
return 0;
}
If it weren't for the array member, the return would be an "rvalue", a value that is just a copy of the value that you have inside the return expression. If you have
struct toto {
double a;
};
struct toto g(void) {
struct toto retval = { 0.0 };
...
return retval;
}
int main(void) {
printf("%g\n", g().a);
}
The argument of the printf call sees a copy of the variable retval that is used inside the function. g().a calls the function and uses the .a field of the return value.
This return value is and
entity that is not an object but only lives because of its "value", called rvalue in the C jargon. It only can be found on the RHS of an assignment, thus the "r" in "rvalue".
The case that you are giving is actually specially treated, because a "value" is not sufficient for all use cases of the array. So this generates a so-called "object with temporary lifetime". This is needed because if you'd do ret_stupid().v[2] the [] operator wants to have a pointer, and a pointer can only point to an object, not a value.
These objects only "live" inside the expression that contains the function call, and even though they are not const qualified you are not allowed to modify them.
So all in all, this is a corner case of C, and you shouldn't abuse it.

Why am I using x->y = z instead of x.y = z in my C code?

I'm following instructions to create code for a flexible array, and I am told to use
x->y = z instead of x.y = z. What would be the reason to use pointers instead of just assigning values normally?
This code includes a custom library flexarray.h which I'll put at the bottom
flexarray.c:
struct flexarrayrec{
int capacity;
int itemcount;
int *items;
};
flexarray flexarray_new(){
flexarray result = emalloc(sizeof *result);
result->capacity = 2;
result->itemcount = 0;
result->items = emalloc(result->capacity * sizeof result->items[0]);
return result;
}
flexarray.h:
#ifndef FLEXARRAY_H_
#define FLEXARRAY_H_
typedef struct flexarrayrec *flexarray;
extern void flexarray_append(flexarray f, int item);
extern void flexarray_free(flexarray f);
extern flexarray flexarray_new();
extern void flexarray_print(flexarray f);
extern void flexarray_sort(flexarray f);
#endif
x->y is just syntax sugar for this
(*x).y
Looks like flexarray is just typedef for *flexarrayrec, so when you write flexarray result, compiler will "transform" it to
flexarrayrec *result = emalloc(sizeof(flexarrayrec));
So result.capacity, for example, would have no meaning as pointer is just a number (memory address), "it doesn't have any field". (*result).capacity will work, but it's frustrating to write so many asterisks and parentheses, that's why we use -> operator :)
x->y is equivalent to (*x).y (it is syntactic sugar)
That is, if x is a pointer.
If your structure (or object) is not a pointer, you can use x.y (and not x->y)
In your case you must use dynamic allocation (pointers), since you want to use flexarray outside of the function flexarray_new().
Your flexarray is a pointer of struct flexarrayrec type. So-
typedef struct flexarrayrec *flexarray;
When you have structure pointer's you have to use -> arrow operator to access structure members!
But if you have declared
typedef struct flexarrayrec flexarray; // Static declaration
Now you are allowed to use . dot operator to access its members!
If you want to use . means you can follow-
(*x).y = z instead of x->y = z;

Resources