2

i just started learning pointers in c. right now i am trying to understand pointers in structures. i don't think i am interpreting them right. the following is the example given in textbook for pointers in structures.

#include<stdio.h>
int main(void)
{
  struct intPtrs
  {
    int *p1;
    int *p2;
  };

  struct intPtrs pointers;
  int i1=100,i2;

  pointers.p1=&i1;
  pointers.p2=&i2;

  *pointers.p2=-97; //here

  printf ("i1 = %i, *pointers.p1 = %i\n", i1, *pointers.p1);
  printf ("i2 = %i, *pointers.p2 = %i\n", i2, *pointers.p2); 
  return 0;

}

my question in the above code is since pointers is declared as a type struct intPtrs , shouldn't the above code look like pointers.(*p1) = -97; . Also, i know it's wrong since it's giving me an error. but i am not able to understand why it's *pointers.p1 .

The above question might sound like naive, but please i am trying my best to understand the concepts by myself. so, any help in trying to explain it as simple as possible would be really helpful to me.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
yash
  • 1,357
  • 2
  • 23
  • 34
  • What error does this give you? – EOF Apr 19 '16 at 16:13
  • 1
    The pointer `p1` is a member of the struct and you access it as `pointers.p1`. To dereference it, you use the `*` operator, like `*(pointers.p1)`. Given the operator precedence, the parenthesis are unnecessary. –  Apr 19 '16 at 16:13
  • 2
    There is no difference between a pointer in a `struct` and a pointer elsewhere. You have a problem with operator preceedence. – too honest for this site Apr 19 '16 at 16:14
  • Your studies are not complete without looking at the *pointer to member* operator `->`, although that is not immediately relevant here. – Bathsheba Apr 19 '16 at 16:15
  • @EOF `error: use of undeclared identifier 'p2'` – yash Apr 19 '16 at 16:20
  • @buggenerator: Not for the code you've posted. – EOF Apr 19 '16 at 16:21
  • 1
    @EOF when i change it from `*pointer.p2` to `pointer.(*p2)` . it's giving me the above error. is that what you were asking? – yash Apr 19 '16 at 16:22
  • @YvesDaoust thank you. also could you explain for the following code. this one is pointer to a structure. `struct entry { int x; }; struct entry a; struct entry *b; b=&a; (*b).x=10;` i couldn't visualize the difference between them pointer to a structure and pointer in a structure. – yash Apr 19 '16 at 16:27
  • @buggenerator: I strongly advise to read a C book. You will not get the whole picture by asking particular questions. (And stack overflow is not a tutoring site or forum). – too honest for this site Apr 19 '16 at 16:34
  • @Olaf where do you think i am reading? i am currently reading **Programming in C** by **stephen G. Kochan** . i am trying to get a better understanding of everything before i move on to further topics. i googled and looked on many websites. once i came to a conclusion that i couldn't find anywhere, i am using stackoverflow. believe me, stackoverflow is my last option for this. – yash Apr 19 '16 at 16:37
  • 1
    @buggenerator: As I'm no clairvoyant, I cannot know what you do. But if you don't understand from that book, maybe you should use a different one. Not every book is equally good for all readers. (but quite some books are bad for all readers). – too honest for this site Apr 19 '16 at 16:50
  • Thank you @Olaf. i will try another book then. – yash Apr 19 '16 at 16:55
  • `i am currently reading Programming in C by stephen G. Kochan` Well you should get you a newer Book. The Author doesn't even use a C compiler, if there is a need of cast. The Author mention also this =>> `Remember that both malloc and calloc are defined to return a pointer to void and, as noted, this pointer should be type cast to the appropriate pointer type.` . He also use `%i` instead of `%d`...that is not wrong for `printf`, but for `scanf` is a different story. Any way check Chapter `10`, Page `386`. It happens that I have this BOOK. – Michi Apr 19 '16 at 16:58
  • damn. i didn't know those. i stumbled upon this [link](http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list) in stackoverflow and i picked the first one in beginner @Michi – yash Apr 19 '16 at 17:02

2 Answers2

4

Have a look at the precedence table.

In your code, p2 is a member variable. The way to access it is to via the member access operator of the structure variable. So, pointers.p2 is the expression you need to actually access p2.

Now, coming to the syntax, the member access operator (.) has higher precedence over indirection (*). so, for the statement,

*pointers.p2=-97; //here

is equivalent to

*(pointers.p2) = 97; //here

which basically tells, access the member p2 of structure variable pointers and dereference it.

OTOH, if you try anything like *p2, that will be invalid, because, there exist no variable named p2 which can be de-referenced.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Not the downvoter, but operator precedence is actually not a thing in C++. May be it is not a thing in C as well? – SergeyA Apr 19 '16 at 16:16
  • @SergeyA: It is "a thing" is both languages for sure. But maybe you mean a different "thing"? – too honest for this site Apr 19 '16 at 16:17
  • @SergeyA, what do you mean not thing!? It's the whole reason `->` was added, to avoid the clunky `(*struct_ptr).member` – StoryTeller - Unslander Monica Apr 19 '16 at 16:17
  • @Olaf C++ standard doesn't have a single word on operator precedence. This is what I call 'not a thing'. – SergeyA Apr 19 '16 at 16:21
  • @SergeyA I can assure, `C11` has the word _precedence_. :) – Sourav Ghosh Apr 19 '16 at 16:22
  • @SergeyA: http://port70.net/~nsz/c/c11/n1570.html#note85 and others (just a simple search). – too honest for this site Apr 19 '16 at 16:27
  • 2
    @SergeyA: Operator precedence is most certainly a "thing" in C++ as well as C; it's specified by the language grammar. Given a the productions *`add-expr`* `:` *`add-expr add-op mul-expr`* and *`mul-expr`* `:` *`mul-expr mul-op pm-expr`*, this shows that multiplicative operators (`*`, `/`, and `%`) have higher precedence than additive operators (`+`, `-`), and that they are right-associative. – John Bode Apr 19 '16 at 17:53
  • @JohnBode, this is a thing - a grammar. Operator precendence tables are attempt to extract the rules from the grammar and present it in a simple tabular format. And you know why those tables are not part of the standard? Because it is impossible to express whole grammar in such table. – SergeyA Apr 19 '16 at 19:07
  • 1
    @SergeyA: Let's back up a bit - you said operator precedence "isn't a thing" in C++, which most of us understood to mean that you were claiming C++ doesn't *define* operator precedence, which is not the case. If you meant that operator precedence "isn't a thing" in the sense that the C++ standard doesn't *summarize* those precedence rules in a handy table, then yes, that's true, but referring to a precedence table somebody else created *based on* those rules shouldn't be a problem. – John Bode Apr 19 '16 at 20:15
  • @JohnBode, im my view, no formal authoritive answer should use such a precedence table and instead should either just say mention the fact that 'according to grammar, operator this will be executed before operator that' or provide corresponding grammar if author believes in benefit of it. Otherwise the answer is not authoritive anymore in my view. 'As long as they are accurate' - what if they are not? – SergeyA Apr 19 '16 at 20:19
-1

In C++, the syntax pointers.*p1 would be used with pointer-to-member. However, C doesn't have pointers-to-members.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • I don't see how that would work actually. Which language you know supports such a syntax? A "pointer to member" would actually be the same as a "pointer to type_of_member" – too honest for this site Apr 19 '16 at 16:16
  • @Olaf, my bad, copied parenthies where they are not needed. And no, pointer to member is **not** the same as pointer to type of member. – SergeyA Apr 19 '16 at 16:20
  • @SergeyA: Hmm, I think you mean something like `struct s { int i, j } st;` `*(int *)((char *)&st + offsetof(st, j))`?, i.e. the pointer based on the offset of the member in its `struct`? I wonder what that would be good for. – too honest for this site Apr 19 '16 at 16:22
  • @Olaf, no, I meant pointer to member. This is a valid construct in C++. I believe, it is offtopic here, but I typed it already. – SergeyA Apr 19 '16 at 16:23
  • @Olaf, yeah but unlike this monstrosity that needs to be wrapped in a macro, C++ has a more type safe monstrosity which Sergey points out. – StoryTeller - Unslander Monica Apr 19 '16 at 16:24
  • @StoryTeller:, SergeyA: I still try to see an application for this. Out of curiosity: Does anyone have a like to a (simple) use-case? – too honest for this site Apr 19 '16 at 16:25
  • @Olaf, I don't know about pointers to member variables, but pointers to member functions have similar syntax and come in handy in certain situations. – StoryTeller - Unslander Monica Apr 19 '16 at 16:29
  • @StoryTeller: You mean C or C++? In c these are simple function pointers (there are no member functions), in C++ the semantic is hidden and inherent in the dot-operator). Yes, they are useful, but this is about member pointers, somehow based on the `struct`s base-address considering the syntax (which is already done by the dot-operator). – too honest for this site Apr 19 '16 at 16:32
  • @Olaf, it is useful for generic access to members. Will think of an example. – SergeyA Apr 19 '16 at 18:02
  • @Olaf, for example, I've used it to perform some mapping between two similar, but different structs. Consider `structX { int x1, y2; };` and `structY { int y1, y2; };` Let's say you need to convert objects of type X to Y and vice versa (and structs actually have more than hundred members). While one can have two simple functions containing `x.x1 = y.y1;` and `y.y1 = x.x1` it is not practical - since you will have two huge largely same functions. It suits instead to define two arrays of pointers to members for both X and Y, and than assign one to another in a loop depending on direction. – SergeyA Apr 19 '16 at 20:22
  • @SergeyA: So you would basically put the the offsets of the members into the array with the compiler doing actually what I wrote explicitly for C some comments above implicitly behind the scenes. Ok, that is an application. Although I'm not sure why not use a common base-class for the similar `struct`s and use normal copy for it. Anyway, thanks for the info, I'll keep that in mind. – too honest for this site Apr 19 '16 at 20:30
  • @Olaf, it is a type-safe version of offsets, but much preferred. A lot of C++ code is a type-safe C code :) Actually, if memory serves, the first C++ compiler was generating C code to be compiled by C compiler. As for common base, I was talking about glue code, which would glue together two completely independent systems. – SergeyA Apr 19 '16 at 20:42
  • @SergeyA: I very well know the history of C and C++. I'm just not up-to-date with C++ features. At least the more "obscure" ones (no offence). I just prefer the more general class concept and much more powerful features of Python if I use a OOP language. C for speed, Python for fancy coding ;-) – too honest for this site Apr 19 '16 at 20:46
  • @Olaf, are you aware that there are cases when C++ produces **faster** code than C? – SergeyA Apr 19 '16 at 20:50
  • @SergeyA: I work in a very special area of programming where not always C++ is an option - left apart its nuisances. Anyway, you can always write code in C which performs worse than any other language, including C++ (the same is true for any other language, including Assembler). But OTOH, you can always write C code which is at least as fast as C++ code. Note this does not mean an identical system architecture. But feel free to prove me wrong. – too honest for this site Apr 19 '16 at 23:03
  • @Olaf, I can give you an example. Let's say, you have two global arrays initialized at compile time, and you want to produce the third one which would be a concatenation of those. In C++ you can write a code which will be optimized into no code - just data segment filled with the data. C doesn't give you that. Of course, you can always retype the whole third array - but I prefer compiler doing the job for me. – SergeyA Apr 20 '16 at 14:46
  • @SergeyA: Just to make sure: The third array is also filled at compile-time and all arrays are read/write? That very well would be possible in C, too. Agreed, it likely would not be that elegant, but possible. Just use macros. I never wrote you have to use the same constructs. If you are in Rome behave like a Roman. – too honest for this site Apr 20 '16 at 15:54