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
Related
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].
I've recently found this page:
Making PyObject_HEAD conform to standard C
and I'm curious about this paragraph:
Standard C has one specific exception to its aliasing rules precisely designed to support the case of Python: a value of a struct type may also be accessed through a pointer to the first field. E.g. if a struct starts with an int , the struct * may also be cast to an int * , allowing to write int values into the first field.
So I wrote this code to check with my compilers:
struct with_int {
int a;
char b;
};
int main(void)
{
struct with_int *i = malloc(sizeof(struct with_int));
i->a = 5;
((int *)&i)->a = 8;
}
but I'm getting error: request for member 'a' in something not a struct or union.
Did I get the above paragraph right? If no, what am I doing wrong?
Also, if someone knows where C standard is referring to this rule, please point it out here. Thanks.
Your interpretation1 is correct, but the code isn't.
The pointer i already points to the object, and thus to the first element, so you only need to cast it to the correct type:
int* n = ( int* )i;
then you simply dereference it:
*n = 345;
Or in one step:
*( int* )i = 345;
1 (Quoted from: ISO:IEC 9899:201X 6.7.2.1 Structure and union specifiers 15)
Within a structure object, the non-bit-field members and the units in which bit-fields
reside have addresses that increase in the order in which they are declared. A pointer to a
structure object, suitably converted, points to its initial member (or if that member is a
bit-field, then to the unit in which it resides), and vice versa. There may be unnamed
padding within a structure object, but not at its beginning.
You have a few issues, but this works for me:
#include <malloc.h>
#include <stdio.h>
struct with_int {
int a;
char b;
};
int main(void)
{
struct with_int *i = (struct with_int *)malloc(sizeof(struct with_int));
i->a = 5;
*(int *)i = 8;
printf("%d\n", i->a);
}
Output is:
8
Like other answers have pointed out, I think you meant:
// Interpret (struct with_int *) as (int *), then
// dereference it to assign the value 8.
*((int *) i) = 8;
and not:
((int *) &i)->a = 8;
However, none of the answers explain specifically why that error makes sense.
Let me explain what ((int *) &i)->a means:
i is a variable that holds an address to a (struct with_int). &i is the address on main() function's stack space. This means &i is an address, that contains an address to a (struct with_int). In other words, &i is a pointer to a pointer to (struct with_int). Then the cast (int *) of this would tell the compiler to interpret this stack address as an int pointer, that is, address of an int. Finally, with that ->a, you are asking the compiler to fetch the struct member a from this int pointer and then assign the value 8 to it. It doesn't make sense to fetch a struct member from an int pointer. Hence, you get error: request for member 'a' in something not a struct or union.
Hope this helps.
New to StackOverflow and new to C. I'm trying to take a struct as a parameter in a function 'add_fields', which adds the first two int fields 'a' and 'b' and puts the result in int field 'c'. Not getting anything from the compiler, so obviously I'm doing something wrong. I just don't know what. Any help would be appreciated.
#include <stdio.h>
struct add{
int a;
int b;
int c;
}
void add_fields(struct add *d){
d->c = a + b;
}
main(){
struct add data;
data.a = 1;
data.b = 2;
data.c = 0;
add_fields(data);
printf("%d + %d = %d", data.a, data.b, data.c);
}
You're very close, but variables a and b don't exist in that context, rather you need to access the fields via the pointer to struct d:
d->c = d->a + d->b;
Second, you need to pass a reference to the struct (since add_fields expects a pointer) when you call add_fields:
add_fields(&data);
The & indicates that you're going to pass the address of the variable data rather than the value.
Here is your corrected code:
#include <stdio.h>
struct add{
int a;
int b;
int c;
};
void add_fields(struct add *d){
d->c = d->a + d->b;
}
int main(){
struct add data;
data.a = 1;
data.b = 2;
data.c = 0;
add_fields(&data);
printf("%d + %d = %d", data.a, data.b, data.c);
return 0;
}
You forgot a semicolon after the struct definition.
I had to fix your add_fields function. You didn't use your struct for a and b.
You needed to pass a pointer into add_fields (hence the &) in the function call. By passing a pointer in, your changes in add_fields were reflected on the outside calling struct.
main always returns an int.
There are several issues:
In main, data is of type struct add. When you call add_field, you need to pass it a struct add* (that is, a pointer to a struct add). To get a pointer to data in main, you need to use the & operator:
add_fields(&data);
In add_fields, you need to use the "member access syntax" (the ->) to access a and b.
Two other minor issues: main should have a return type of int:
int main() { ...
and you need to place a semicolon after the closing } of a struct definition.
C is call by value language. When you pass data, you are passing a copy of the object of type struct add. In your add_fields field, you are accepting a pointer to the struct. Since you want to change the fields of the struct, you should pass the address of the data struct (and accept a pointer to it in add_fields). To do this,
add_fields(&data);
Also, in add_fields, you aren't have undefined variables (a and b). I assume they should be from the struct, as well?
You should be passing the memory address of the struct to the add_fields function.
add_fields(&data)
** Wow I was really slow on this one :P
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;
}
Is there an easy explanation for what this error means?
request for member '*******' in something not a structure or union
I've encountered it several times in the time that I've been learning C, but I haven't got a clue as to what it means.
It also happens if you're trying to access an instance when you have a pointer, and vice versa:
struct foo
{
int x, y, z;
};
struct foo a, *b = &a;
b.x = 12; /* This will generate the error, should be b->x or (*b).x */
As pointed out in a comment, this can be made excruciating if someone goes and typedefs a pointer, i.e. includes the * in a typedef, like so:
typedef struct foo* Foo;
Because then you get code that looks like it's dealing with instances, when in fact it's dealing with pointers:
Foo a_foo = get_a_brand_new_foo();
a_foo->field = FANTASTIC_VALUE;
Note how the above looks as if it should be written a_foo.field, but that would fail since Foo is a pointer to struct. I strongly recommend against typedef:ed pointers in C. Pointers are important, don't hide your asterisks. Let them shine.
You are trying to access a member of a structure, but in something that is not a structure. For example:
struct {
int a;
int b;
} foo;
int fum;
fum.d = 5;
It may also happen in the following case:
eg. if we consider the push function of a stack:
typedef struct stack
{
int a[20];
int head;
}stack;
void push(stack **s)
{
int data;
printf("Enter data:");
scanf("%d",&(*s->a[++*s->head])); /* this is where the error is*/
}
main()
{
stack *s;
s=(stack *)calloc(1,sizeof(stack));
s->head=-1;
push(&s);
return 0;
}
The error is in the push function and in the commented line. The pointer s has to be included within the parentheses. The correct code:
scanf("%d",&( (*s)->a[++(*s)->head]));
I have enumerated possibly all cases where this error may occur in code and its comments below. Please add to it, if you come across more cases.
#include<stdio.h>
#include<malloc.h>
typedef struct AStruct TypedefedStruct;
struct AStruct
{
int member;
};
void main()
{
/* Case 1
============================================================================
Use (->) operator to access structure member with structure pointer, instead
of dot (.) operator.
*/
struct AStruct *aStructObjPtr = (struct AStruct *)malloc(sizeof(struct AStruct));
//aStructObjPtr.member = 1; //Error: request for member ‘member’ in something not
//a structure or union.
//It should be as below.
aStructObjPtr->member = 1;
printf("%d",aStructObjPtr->member); //1
/* Case 2
============================================================================
We can use dot (.) operator with struct variable to access its members, but
not with with struct pointer. But we have to ensure we dont forget to wrap
pointer variable inside brackets.
*/
//*aStructObjPtr.member = 2; //Error, should be as below.
(*aStructObjPtr).member = 2;
printf("%d",(*aStructObjPtr).member); //2
/* Case 3
=============================================================================
Use (->) operator to access structure member with typedefed structure pointer,
instead of dot (.) operator.
*/
TypedefedStruct *typedefStructObjPtr = (TypedefedStruct *)malloc(sizeof(TypedefedStruct));
//typedefStructObjPtr.member=3; //Error, should be as below.
typedefStructObjPtr->member=3;
printf("%d",typedefStructObjPtr->member); //3
/* Case 4
============================================================================
We can use dot (.) operator with struct variable to access its members, but
not with with struct pointer. But we have to ensure we dont forget to wrap
pointer variable inside brackets.
*/
//*typedefStructObjPtr.member = 4; //Error, should be as below.
(*typedefStructObjPtr).member=4;
printf("%d",(*typedefStructObjPtr).member); //4
/* Case 5
============================================================================
We have to be extra carefull when dealing with pointer to pointers to
ensure that we follow all above rules.
We need to be double carefull while putting brackets around pointers.
*/
//5.1. Access via struct_ptrptr and ->
struct AStruct **aStructObjPtrPtr = &aStructObjPtr;
//*aStructObjPtrPtr->member = 5; //Error, should be as below.
(*aStructObjPtrPtr)->member = 5;
printf("%d",(*aStructObjPtrPtr)->member); //5
//5.2. Access via struct_ptrptr and .
//**aStructObjPtrPtr.member = 6; //Error, should be as below.
(**aStructObjPtrPtr).member = 6;
printf("%d",(**aStructObjPtrPtr).member); //6
//5.3. Access via typedefed_strct_ptrptr and ->
TypedefedStruct **typedefStructObjPtrPtr = &typedefStructObjPtr;
//*typedefStructObjPtrPtr->member = 7; //Error, should be as below.
(*typedefStructObjPtrPtr)->member = 7;
printf("%d",(*typedefStructObjPtrPtr)->member); //7
//5.4. Access via typedefed_strct_ptrptr and .
//**typedefStructObjPtrPtr->member = 8; //Error, should be as below.
(**typedefStructObjPtrPtr).member = 8;
printf("%d",(**typedefStructObjPtrPtr).member); //8
//5.5. All cases 5.1 to 5.4 will fail if you include incorrect number of *
// Below are examples of such usage of incorrect number *, correspnding
// to int values assigned to them
//(aStructObjPtrPtr)->member = 5; //Error
//(*aStructObjPtrPtr).member = 6; //Error
//(typedefStructObjPtrPtr)->member = 7; //Error
//(*typedefStructObjPtrPtr).member = 8; //Error
}
The underlying ideas are straight:
Use . with structure variable. (Cases 2 and 4)
Use -> with pointer to structure. (Cases 1 and 3)
If you reach structure variable or pointer to structure variable by following pointer, then wrap the pointer inside bracket: (*ptr). and (*ptr)-> vs *ptr. and *ptr-> (All cases except case 1)
If you are reaching by following pointers, ensure you have correctly reached pointer to struct or struct whichever is desired. (Case 5, especially 5.5)
It may means that you forgot include a header file that define this struct/union.
For example:
foo.h file:
typedef union
{
struct
{
uint8_t FIFO_BYTES_AVAILABLE : 4;
uint8_t STATE : 3;
uint8_t CHIP_RDY : 1;
};
uint8_t status;
} RF_CHIP_STATUS_t;
RF_CHIP_STATUS_t getStatus();
main.c file:
.
.
.
if (getStatus().CHIP_RDY) /* This will generate the error, you must add the #include "foo.h" */
.
.
.
can also appear if:
struct foo { int x, int y, int z }foo;
foo.x=12
instead of
struct foo { int x; int y; int z; }foo;
foo.x=12
I saw this when I was trying to access the members.
My struct was this:
struct test {
int a;
int b;
};
struct test testvar;
Normally we access structure members as
testvar.a;
testvar.b;
I mistook testvar to be a pointer and did this.
testvar->a;
That's when I saw this error.
request for member ‘a’ in something not a structure or union
My ridiculous experience is that I incorrectly put '.' instead of ','.
printf("%c". ch);