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

Pages: 1-4041-8081-

C89 structs

Name: Anonymous 2010-08-30 0:37

Hi /prog/. When I program C I usually just use whatever features gcc allows without really worrying about different standards. However, I am now trying to learn strict C89. I know that it's no longer "standard" C, but I want to learn it anyways.

typedef struct {
    int a, b;
} s;


So normally, if I wanted to return an s from a function I would just use return (s) {1, 2};, but apparently that's not allowed in C89. So right now I'm using
s res;
res.a = 1;
res.b = 2;
return res;


Is there a better/shorter way to do this?

Thanks.

Name: Anonymous 2010-08-30 0:40

Returning a struct is poor form.

Name: Anonymous 2010-08-30 0:41

/prog/ is not stackoverflow.

Name: Anonymous 2010-08-30 0:42

>>2
Asplain. Seems like good form to me.

Name: Anonymous 2010-08-30 0:45

>>2
OP here. Is a pointer to a struct acceptable? How else should I return multiple values?

>>3
Feel free to ignore this thread and return to "READ SICP LOL" and Java vs. C#.

Name: Anonymous 2010-08-30 0:59

Pass in the pointer to the struct from the caller and have the callee fill it in.

Name: Anonymous 2010-08-30 1:00

>>6
Why would anyone ever even think of arguing that when Java is the obvious superior?

Name: Anonymous 2010-08-30 1:04

>>6
Yeah, I thought of that after I posted >>5.

But for the specific example I was working on, it seems like overkill. I'm trying to return a vector (a struct of 3 doubles) so there's not too much overhead when returning it.

I'd also like to be able to do something like:
vector a, b, c, d;

d = add(a, cross(b, c));


and doing it the way you suggested would make that code a lot longer. (although I guess I shouldn't be whining about the length if I'm using C)

So, is it really that bad to return a struct in this case?

And thanks for your help.

Name: Anonymous 2010-08-30 1:06

>>8
vector
...And I guess this is the point when everybody assumes I'm a kid trying to program a game. It's a raytracer, if anybody cares.

Name: Anonymous 2010-08-30 1:34

>>9
Your words, not mine.

I don't see what the concern is.  Brevity of code is a luxury; brevity of execution is an important aspect for C.

Name: Anonymous 2010-08-30 1:42

>>9
d = add(a, cross(b, c));

Returning structs is considered poor form for pretty much this precise reason. Imagine if your vector class had dynamically allocated memory, you are going to leak that shit all over the place whenever you try and write concise code, not to mention you will end up confusing yourself when half of the vectors are on the heap and the other half are on the stack.

This style is also rather inefficient for a ray tracer, due to the number of vectors that will be created on the stack. 6-8 vectors will be created just to calculate a refracted ray, where you could do it in place with 2.

A much nicer way to do it is, in my opinion:

typedef struct {
    float x;
    float y;
    float z;
} Vector3f;

void add(const Vector3f* a, const Vector3f* b, Vector3f* c);
void inplaceadd(Vector3f* a, const Vector3f* b);
void cross(const Vector3f* a, const Vector3f* b, Vector3f* c);
void inplacecross(Vector3f* a, const Vector3f* b)

Name: Anonymous 2010-08-30 2:02

>>1
No, compound literals are a C99 feature. (which I recommend very much over C89 unless you're targeting microcontroller compilers, which aren't going to fully conform to any standard anyway)

>>11
If you dynamically allocate memory for this, you're doing it wrong.

Anyway, for simple vector arithmetic like this you want to make the functions inline, for which any modern compiler will generate about the same code for pointers or pass by value.
But again, not a C89 feature...

Name: Anonymous 2010-08-30 2:14

>>12
If you dynamically allocate memory for this, you're doing it wrong.
For the simple problem OP is describing, I agree.

I take it you have never written a raytracer in C89 however, because you will need functions to facilitate creation of objects, lights, materials and so on, doing this on the stack is not possible.

Name: Anonymous 2010-08-30 4:14

This thread makes me nostalgic.  My ray-tracer in grad school even had anti-aliasing!

>>1, your ray-tracer had better not allow anything other than spheres, because it isn't a real ray-tracer if it does.

Name: Anonymous 2010-08-30 7:06

>>1
[size=6]lol[/size]

Name: Anonymous 2010-08-30 9:34

>>11
This guy's got it correct, except his naming conventions suck. If I were you I'd also make all the pointers __restrict. You'll get faster code; just make sure you don't send the same address for multiple arguments (that's why you need in-place versions as separate functions.) Your code in >>8 becomes:

inplacecross(&b, &c);
add(&a, &b, &d)


You would implement the in-place versions as wrappers that use a temporary (because of __restrict), like this:

static __inline void inplaceadd(Vector3f* __restrict a, const Vector3f* __restrict b) {
    Vector3f out;
    add(a, b, &out);
    memcpy(a, &out, sizeof(*a));
}


Returning structs is rarely a good idea. Older compilers (pre-C89) don't even support this (though you're extremely unlikely to run into one of those today). With GCC you can set -Waggregate-return to warn if you attempt to do this.

Unfortunately, writing code with pointers instead of literal return values is going to be a bit more verbose than you'd like. That's just the way C is; don't like it, don't code in C.

Name: Anonymous 2010-08-30 9:42

>>16
He said he wanted to use C89, not GNU89

Name: Anonymous 2010-08-30 10:55

Alright, I guess I'll just do what >>6 suggested and use in-place versions when possible.

Thanks for your help, everybody.

Name: Anonymous 2010-08-30 11:02

>>16
And your 'out' parameter should always be first. To do otherwise, or with the mixed-up style you're apparently advocating, will cause no end of confusion when you're trying to use that code later.

Name: Anonymous 2010-08-30 13:16

>>17
The extensions __inline and __restrict are supported on all popular compilers. If they aren't supported, you can just #define them away and the code will still work correctly. They are merely optimization hints, nothing more.

Name: Anonymous 2010-08-30 13:37

>>20
What are __inline and __restrict?

Name: Anonymous 2010-08-30 14:15

>>21
Seriously, you can't google it?

Here's a good article explaining restrict:
http://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html

Name: Anonymous 2010-08-30 14:20

>>20
The point is that by using them, your program no longer conforms to strict C89. >>1 stated that he wanted to learn strict C89, not C89 plus common compiler extensions.

Name: Anonymous 2010-08-30 14:28

>>22
I read that shit once, and it didn't help me much.  Seriously, what the fuck is this shit?

[code]  float* restrict acceleration_x = &acceleration->x;
  float* restrict velocity_x     = &velocity->x;
  float* restrict position_x     = &position->x;
  float* restrict acceleration_y = &acceleration->y;
  float* restrict velocity_y     = &velocity->y;
  float* restrict position_y     = &position->y;
  float* restrict acceleration_z = &acceleration->z;
  float* restrict velocity_z     = &velocity->z;
  float* restrict position_z     = &position->z;[code]

Name: Anonymous 2010-08-30 14:38

>>24
It's a whole lot of overkill. You can just get away with declaring the arguments restrict and you will probably get the same behavior.

Doing all the reads up-front (the const block) does help push the loads up which will make it faster, but you really shouldn't be doing that without profiling it anyway. Just write it naturally but declare the arguments restrict.

>>23
If you wrap them in a define, which you should do anyway, then it IS strict C89.

#ifdef __GNUC__
#define INLINE __inline
#define RESTRICT __restrict
#else
#define INLINE
#define RESTRICT
#endif

Name: Anonymous 2010-08-30 16:13

>>25

#ifdef __GNUC__
    #define INLINE __inline
    #define RESTRICT __restrict
#else
    #define INLINE do { fork(); } while (1);
    #define RESTRICT do { fork(); } while (1);
#endif

Name: Anonymous 2010-08-30 16:21

>>26
That will not compile. You must be a baka.

Name: Anonymous 2010-08-30 16:35

>>26
If you must indent preprocessor statements, It's better to do it like this:

#ifdef __GNUC__
#define     INLINE __inline
#define     RESTRICT __restrict
#else
#define     INLINE do { fork(); } while (1);
#define     RESTRICT do { fork(); } while (1);
#endif

Name: Anonymous 2010-08-30 16:40

>>28
C99 in a discussion about __inline and __restrict.
Good job following the conversation there, sparky.

Name: Anonymous 2010-08-30 16:45

>>29
asplain

Name: Anonymous 2010-08-30 17:41

>>29
what the fuck
the entire fucking point of indentation is to allow the eye to quickly group statements into related blocks based on how lefthand whitespace. whatever the fuck you're trying to do fails completely at that.

as does the fucktarded
#ifdef __GNUC__
#    define INLINE __inline
#    define RESTRICT __restrict
#else
#    define INLINE do { fork(); } while (1);
#    define RESTRICT do { fork(); } while (1);
#endif

before anyone tries to suggest that.

Name: Anonymous 2010-08-30 17:44

>>28
Modern compilers CANNOT derive the same guarantees as restrict unless the function is inlined, or using LTO/whole-program optimization/whatever you want to call it. And even then it's likely to miss cases in which you could trivially add it, especially for a library.

Name: Anonymous 2010-08-30 19:57

All pointers should be restrict by default. Every EXPERT PROGRAMMER must agree with this.

Name: Anonymous 2010-08-30 20:47

>>32
Implying fork exists on platforms that don't use GCC.

Name: Anonymous 2010-08-30 20:48

>>34
Wrong, they shouldn't be restrict when the may potentially overlap.

Look at strcmp for example. The input pointers aren't restrict for that very reason.

Name: Anonymous 2010-08-30 21:23

>>36
then why are the arguments to strcpy and strncpy restrict?

Name: Anonymous 2010-08-30 22:04

>>37
Error: attempt to contextualize expression while lacking suitable context:
then why are the arguments to strcpy and strncpy restrict?
^----------- here.

Name: Anonymous 2010-08-30 22:17

>>36
Who cares about overlapping blocks? That should always be of the (API user) programmer's concern. It's just your fault if you pass in things that overlap.

Name: Anonymous 2010-08-31 5:19

>>35
Implying
Please don't do that.

Name: Anonymous 2010-08-31 5:36

>>40
implying your post is going to cause anything but more of this.

Name: Anonymous 2010-08-31 6:04

>>41
More of this.

Name: Anonymous 2010-08-31 10:52

>>42
Less of this.

Name: Anonymous 2010-08-31 11:27

>>43
The same amount of this.

Name: Anonymous 2010-08-31 13:01

>>32
In C89 the # needs to be in the first column. You generally put the indentation after the #, and before the first identifier, so your "fucktarded" solution is actually the correct one.

Most editors will enforce this; that's why they jump to the first column when you type #.

Name: Anonymous 2010-08-31 13:30

>>44
A different amount of this.

Name: Anonymous 2010-08-31 13:38

>>45
I'm glad we aren't stuck using C89 then.

Name: Anonymous 2010-08-31 14:13

>>48
Not Emacs.

Name: Anonymous 2010-08-31 14:42

>>48
I bet it's these brain-rotting §§IDE''s.

Name: Anonymous 2010-08-31 15:20

>>50
§§
FFFFFFFFFFFFFFFFFFFFFFFFF I MAD

Name: Anonymous 2010-08-31 16:17

>>51
This is what's on my keyboard in place of the usual single opening faggot quote.

Name: Anonymous 2010-08-31 16:19

Where did >>48 go?

Name: Anonymous 2010-08-31 16:26

>>52
I remember that discussion. So are you missing any other standard keys, or is that it?

Name: Anonymous 2010-08-31 17:15

>>54
It's an Apple wireless keyboard (http://regmedia.co.uk/2010/06/09/tt_ipad_acc_3.jpg), but I cannot identify the layout.
The keyboard differs from the pictured one in that I don't have the Euro sign on the 2 key and I have the usual octothorpe on the 3 key.

Name: Anonymous 2010-08-31 18:11

>>55
http://support.apple.com/kb/HT2841
It appears to be the English (International) layout.

Name: Anonymous 2010-09-01 6:05

>>45
No it doesn't.

C89 3.8p1:

A preprocessing directive consists of a sequence of preprocessing tokens that begins with a # preprocessing token that is either the first character in the source file (optionally after white space containing no new-line characters) or that follows white space containing at least one new-line character, and is ended by the next new-line character.

Name: >>26 2010-09-01 6:40

>>57
amen

Name: Anonymous 2010-09-01 7:38

>>54
standard keys
IHBT

Name: Anonymous 2010-09-01 8:08

>>59
No, you're just a moron.

Name: Anonymous 2010-09-01 8:18

>>60
You're saying there's a standard for keyboards and their layouts and keys?

Name: Anonymous 2010-09-01 11:26

>>57
Oh interesting. So that leads to my next logical question, which is why the cock shit do editors like Xcode and Vim jump to the first column when I type #? And how the hell do I turn that off?

Name: Anonymous 2010-09-01 11:51

Name: Anonymous 2010-09-01 13:05

>>62
So that leads to my next logical question, which is why the cock shit do editors like Xcode and Vim jump to the first column when I type #?
The answer to that question led to that question? Is this a recursion joke?

Name: Anonymous 2010-09-01 13:12

>>62
Xcode does that because it's §§user-friendly''. Do you feel befriended? Like most user-friendly features of Xcode, it cannot be turned off (because why would you even want to do such a thing‽).

Name: Anonymous 2010-09-01 14:11

>>65
§§
We've been over this[b]![/b]

Name: Anonymous 2010-09-01 14:13

Enforcing LIFO tag closing structure considered harmful!

Name: Anonymous 2010-09-01 16:35

>>67
agreed

Name: Anonymous 2010-09-01 17:13

>>62
It's because the most common style for indenting preprocessor directives is to put the # in the first column. It makes it easy to see which lines are for the preprocessor while still keeping it easy to see the indentation at a glance.

Name: Anonymous 2010-09-01 17:38

This whole time I was under the impression that it was mandatory for standards-compliance. You learn something new every day I guess.

Name: Anonymous 2010-09-01 18:36

>>69
Syntax highlighting can do that too, and with less fucktardedness.

Name: Anonymous 2010-09-01 19:35

Regarding >>1, has anyone actually tested the efficiency of implementing vectors this way in C? The brevity it allows is nice.

Name: Anonymous 2010-09-01 21:27

>>72
Already answered ITT. It's a waste of stack.

Name: Anonymous 2010-09-01 22:19

>>73
Of course it uses more stack, but that doesn't mean it's slower. I'm asking if someone has actually tested it.

Name: Anonymous 2010-09-02 0:32

It doesn't necessarily use more stack. Three floats could be passed in registers...

Name: Anonymous 2010-09-02 1:22

>>75
No C ABI I'm aware of allows for any struct larger than 8 bytes to be passed in registers.

Name: Anonymous 2010-09-02 2:28

>>76
Yeah but they could be inlined. Almost all of your vector functions should be inlined anyway so your compiler can take full advantage of SIMD instructions. Can't the latest SSE set even do shit like dot products in a single instruction these days? (I'm kind of out of the loop.)

And if it is a non-trivial function, then the stack space is the least of your worries. Plus many C++ compilers are used to passing in a pointer to store the return value to avoid an extra by-value copy; there's no reason they wouldn't do the same for C.

Name: Anonymous 2010-09-02 3:46

>>77
This shit ain't being vectorized unless you do it manually.

And yes, if it's inlined obviously it won't create the useless copies. But then nothing will be "passed" to functions either.

C and C++ use basically the same semantics for returning structs, your understanding of C++ is flawed if you think it avoids the extra by-value copies with the same prototypes.

Name: Anonymous 2010-09-02 14:16

>>78
You mean the C++ FAQ Lite is lying to me?

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.9

sad trombone

Name: Anonymous 2010-09-02 14:56

>>79
http://yosefk.com/c++fqa/ctors.html#fqa-10.9

Of course our boring binary logic fails to represent the developers who think they care about performance, although they have a very vague idea about the actual performance of their programs. Those are the people who use the von Neumann model ("you access memory using pointers which are actually indexes of individual bytes") to think about computers, and call this "the low level". They are typically less aware of things like instruction caches (which make big programs slow), SIMD instruction sets (which can give performance gains way beyond "generic" template implementations of numerical algorithms), assembly language and optimizers in general (for example, how restrict helps optimization but const doesn't). These people engage in lengthy discussions about complicated high-level optimizations, their ultimate goal being very generic code which can be compiled to a very efficient program by a very smart compiler, which will never exist.
which will never exist
( ._.)

Name: Anonymous 2010-09-02 23:04

>>76
I think the AIX calling conventions will do this.  It's just that x86 has so few registers.

Name: Anonymous 2010-09-03 0:40

>>81
Why the fuck would you sage this? This thread is actually interesting, and you post an interesting and informative comment, and yet you sage. Now this thread is the last one on the page, and stupid shit like "interbutt radio" is on top.

sage is the cancer that is killing /prog/

Name: Anonymous 2010-09-03 3:17

>>82
Apart from the weak troll, I have to agree. /prog/riders should bump worthy threads and posts -- not that there's that many of them in the first place!

Name: Anonymous 2010-09-03 9:03

>>83
Nah.

Sage every post, and remove the front page entirely.

Name: Anonymous 2010-09-03 9:19

>>82
Since threads never die, it doesn't matter if they are on the front page or not.

Name: Anonymous 2010-09-03 14:25

>>85
Of course it does. If they leave the front page, readers don't see them, so the discussion ends.

Name: Anonymous 2010-09-03 14:44

>>86
Only readers with an inferior /prog/ client don't see them. These people rarely have anything to contribute anyway.

Name: Anonymous 2010-09-03 15:22

>>87
Haha.

Name: VIPPER 2010-09-03 16:50

on /vip/, we dont sage.

Name: VIPPER 2010-09-03 17:46

JEWS

Name: Anonymous 2010-09-03 17:56

>>86
I don't see why you should flood the front page with your crap just because you don't understand how to maintain a conversation.

Name: Anonymous 2010-09-03 19:19

No one ever has ``discussions" past the front page.
Stop kidding yourself.

Name: Anonymous 2010-09-03 21:03

>>92
It's a nice place to have a monologue, bump the thread, and then be indignant at yourself to pretend people do, though.

Name: Anonymous 2010-09-04 2:14

>>82
thanks for ruining the thread, asshole.

Name: Anonymous 2010-11-27 23:39


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