Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

C/C++ is cryptic

Name: Anonymous 2011-08-09 1:16

What does the following C/C++ construction do?

(A->*B)(C,D)[E]

Name: Anonymous 2011-08-09 1:27

Makes people scratch their head? =)

Name: Anonymous 2011-08-09 1:43

C/C++ is not a language.

Name: Anonymous 2011-08-09 3:23

C is not a language.
C++ is not a language.

Name: Anonymous 2011-08-09 3:30

>>1
It depends on the type of A, B, C, D and E.

Name: Anonymous 2011-08-09 4:05

>>5
and if the language is C++, operator overloading...

Name: Anonymous 2011-08-09 4:39

>>1
If you write code like this, it's not your language that is a problem. What have this Python made of you, people.

Name: Anonymous 2011-08-09 5:03


a = [[0]]
a = a * 2
a[0][0] = 1
print str(a)

Name: Anonymous 2011-08-09 9:30

precedence and syntax are evil.

Name: Anonymous 2011-08-09 9:41

>>7
Wrong. B is pointer to struct-field. A->*B dereferences it with object A. Of course it's all static.



Orthogonality and SETQ

You may wonder, what Q part of SETQ stands for.
Once there was just SET, which was first-class.
SET was othogonal, meaning it treated both operands by their values.
SET allowed stuff like:
  set 'A 'B
  set A 123
  B ; evals to 123

But SET was just too powerful and depended on implementation details. Like environment being just dynamic ASSOC-list. And today's environment requires SET to provide address, instead of symbol.

So born ugly and non-orthogonal SETQ, which tries to emulate old SET.

Similar situation with C/C++ class variables, as there is no way to relative-pointer to member.

Name: Anonymous 2011-08-09 9:44

>>1
That is not valid C, moron.

Name: Anonymous 2011-08-09 9:52

Name: Anonymous 2011-08-09 9:55

>>12
Briefly, you're using the pointer as an offset into the class. You can't use this pointers apart from the class they refer to, so:

  int Car::*pSpeed = &Car::speed;
  Car mycar;
  mycar.*pSpeed = 65;

It seems a little obscure, but one possible application is if you're trying to write code for deserializing generic data into many different object types, and your code needs to handle object types that it knows absolutely nothing about (for example, your code is in a library, and the objects into which you deserialize were created by a user of your library). The member pointers give you a generic, semi-legible way of referring to the individual data member offsets, without having to resort to typeless void * tricks the way you might for C structs.

Name: Anonymous 2011-08-09 13:48


I'm not sure, but I think B is a pointer to a function that is stored in a struct (A), and C and D are parameters to that function. Also, the return type is an array.

So, get the E'th return value of B(C,D).

Name: Anonymous 2011-08-09 15:10

>>14
Looks like, except that A is a pointer to a struct. It's not that complicated if you know about function pointers.

Name: Anonymous 2011-08-09 15:34

offsetof.

Sage.

Name: Anonymous 2011-08-09 16:29

>>12,13
That is not valid C, morons.

Name: Anonymous 2011-08-09 18:52

>>12,13
C++ isn't C you stupid faggots.

>>11,17
I encourage your battle against the heathen pigs.

Name: Anonymous 2011-08-09 21:57

>>10
+1 informative!

How about SETF?  I don't even know how it's different from SET and SETQ, or what the F is for.

Name: Anonymous 2011-08-09 22:05

>>19
Avoid SETF. It introduces side-effects in your program.

Name: Anonymous 2011-08-10 0:37

>>19
SETF is pretty nice and very extensible.

Name: Anonymous 2011-08-10 6:11

>>19
SETF can be used as a drop in replacement for SETQ (I think) when used on symbols.
The difference is that SETF can also set fields: (setf (car c) x)

Name: Anonymous 2011-08-10 19:47

>>22
thx

Name: Anonymous 2011-08-10 21:18

>>22
SETF is a macro and thus just expands into a SETQ for the trivial cases (such as assigning a local variable). The difference is of course that you can assign any generalized place, while SETQ only works on variables (lexical, dynamic/"global", ...). Doing a (setf (car x) ...) will usually expand into a (rplaca x ...) (or something even more optimized). For fancier things, it could expand in fairly fancy ways (it's user-extensible and even the default features can be rather complex), here's an example:

(setf (apply #'aref a b) c)
;=>
(LET* ((#:G1146 A) (#:G1147 B))
  (MULTIPLE-VALUE-BIND (#:G1145)
      C
    (APPLY #'(SETF AREF) #:G1145 #:G1146 #:G1147)))

(defstruct test-struct a b c)
(setf (test-struct-a (make-test-struct)) ...)
;=>
(LET* ((#:TMP1159 (MAKE-TEST-STRUCT)))
  (MULTIPLE-VALUE-BIND (#:NEW1158)
      ...
    (FUNCALL #'(SETF TEST-STRUCT-A) #:NEW1158 #:TMP1159)))

(setf (fifth x) ...)
;=>
(LET* ((#:G1164 X))
  (MULTIPLE-VALUE-BIND (#:G1165)
      ...
    (SB-KERNEL:%RPLACA (CDDDDR #:G1164) #:G1165)))

(setf (macro-function 'test) #'(lambda (body env) ...))
;=>
(LET* ()
  (MULTIPLE-VALUE-BIND (#:NEW1184)
      #'(LAMBDA (BODY ENV) ...)
    (FUNCALL #'(SETF MACRO-FUNCTION) #:NEW1184 'TEST)))

Some of these have obvious dead code, but it gets optimized away further during compilation.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List