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

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.

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