Proper C Coding

Programming, for all ages and all languages.
Post Reply
User avatar
Alboin
Member
Member
Posts: 1466
Joined: Thu Jan 04, 2007 3:29 pm
Location: Noricum and Pannonia

Proper C Coding

Post by Alboin »

Every time I write anything substantial in C, I end up writing it as if I were using C++. I have very few global variables, and most data is structured in structs with functions taking the structs as arguments. What is the standard C programming style? If this is it, I think I might just convert a lot of my projects to C++. (Shouldn't be too hard.) Also, is there anything wrong with global variables? I have this paranoia for them, and I can't figure out where it comes form. Thanks!
C8H10N4O2 | #446691 | Trust the nodes.
Solidus117
Posts: 23
Joined: Sun Dec 03, 2006 5:29 pm

Re: Proper C Coding

Post by Solidus117 »

Alboin wrote:Every time I write anything substantial in C, I end up writing it as if I were using C++. I have very few global variables, and most data is structured in structs with functions taking the structs as arguments. What is the standard C programming style? If this is it, I think I might just convert a lot of my projects to C++. (Shouldn't be too hard.) Also, is there anything wrong with global variables? I have this paranoia for them, and I can't figure out where it comes form. Thanks!
There is no 'standard' way of writing code in C.

Global variables, in most cases, should not be used. Just bad for coherence. Using structures as arguments is a perfectly reasonable thing to do, although to improve memory usage, you could just accept a struct pointer in the function parameter.
User avatar
Cheery
Member
Member
Posts: 52
Joined: Wed Oct 18, 2006 4:39 am

Post by Cheery »

There's no good way of writing code in C. You can try, but even if you'd succeed, C would still look ugly and almost unreadable.
Windows Vista rapes you, cuts you and pisses inside. Thought these are just nifty side-effects.
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

Cheery wrote:There's no good way of writing code in C. You can try, but even if you'd succeed, C would still look ugly and almost unreadable.
C looks almost identical to C++, so I am assuming you don't like that either. The major difference is the fact that classes can have member functions that implicitly pass the *this pointer as the first parameter, while in C you have to supply said parameter and it will not automatically call a function upon destruction, you must actually call the constructor and destructor manually. I really don't think it makes it so much more complicated than C++ that it is almost unreadable as stated by Cheery. C can look nice, and it can look ugly, as can C++, assembly, java, scheme, insert any other language you can think of.


I tend to use structs and pass pointers, that way I only pass 4-bytes (8 if you're using a 64-bit machine) rather than the entire struct. I also do tend to use globals depending on what they are used for, if for example, I have a structure that stores information about the display and I am writing a 2d graphics library, I find no reason to pass this around to each and every function when I could make it global and they could all just see it. Saves a lot of data being passed needlessly, so speed is increased, and functions are easier to read since they aren't cluttered with additional parameters. I am very chosey with my globals, but as mentioned if it holds something that a lot of functions require access to I will make it global, if it's something not used often, or only used in a few specific places, I will keep it local.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Cheery wrote:There's no good way of writing code in C. You can try, but even if you'd succeed, C would still look ugly and almost unreadable.
For a person with a nickname of 'cheery' you don't seem all that cheery...

C++ is just C with object oriented features... the only thing is that in C++ you save yourself heaps of function calls and complex code by creating instances of some objects.
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Post by Brynet-Inc »

Cheery wrote:There's no good way of writing code in C. You can try, but even if you'd succeed, C would still look ugly and almost unreadable.
It's not hard to write readable C code, That doesn't look ugly..

C syntax is decided by personal preference really...

I do know a few people with messy coding styles.. But it's definitely not a problem with the C language itself! :roll:
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
earlz
Member
Member
Posts: 1546
Joined: Thu Jul 07, 2005 11:00 pm
Contact:

Post by earlz »

the real question is to use more structs or more args...

which do you prefer

Code: Select all

struct{
  unsigned int a,b,c;
}triple;

BOOL IsPythagoreanTriple(struct triple *is_it); //yea crappy arg name but anyway..
or do you prefer

Code: Select all

BOOL IsPythagoreanTriple(unsigned int a,b,c);
they are both acceptable, and maybe the struct one is better.
but I personally prefer the multipe arg one...
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

hckr83 wrote:the real question is to use more structs or more args...

which do you prefer

Code: Select all

struct{
  unsigned int a,b,c;
}triple;

BOOL IsPythagoreanTriple(struct triple *is_it); //yea crappy arg name but anyway..
or do you prefer

Code: Select all

BOOL IsPythagoreanTriple(unsigned int a,b,c);
they are both acceptable, and maybe the struct one is better.
but I personally prefer the multipe arg one...
It depends on what you're aim is... I normally worry about performance in all of my graphics libs, so passing a pointer to a struct is much faster than passing many many params, especially in something like my software 3d engine where I am passing 3 vertices, texture coordinates, color and light data, etc. Of course, having to access a data member of a struct takes a little time as well, but in most cases where I've written both methods to compare (again thinking back to my 3d software renderer) I saw significant speed increases passing pointers to structs.
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Post by Colonel Kernel »

pcmattman wrote:C++ is just C with object oriented features
I suppose for kernel development and embedded systems, this is how C++ turns out most of the time. In general though, C++ is a much more vast and complex language than C. It's not just OO either, it's really multi-paradigm. You can write C-style procedural code in C++, "plain-old" OO-style, or functional style (see <algorithm> and <functional> in the STL for starters).

Personally, I think the one most underrated feature of C++ is templates -- they could be extremely useful even for low-level problem domains like kernel programming. My $0.02...

And yes, it is possible to make C look almost as concise as C++. It just takes a lot of extra work. Just because C has no object-oriented features doesn't mean you can't implement an OO design in it (this is how my kernel code is structured).
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

hckr83 wrote:the real question is to use more structs or more args...

which do you prefer

Code: Select all

struct{
  unsigned int a,b,c;
}triple;

BOOL IsPythagoreanTriple(struct triple *is_it); //yea crappy arg name but anyway..
or do you prefer

Code: Select all

BOOL IsPythagoreanTriple(unsigned int a,b,c);
they are both acceptable, and maybe the struct one is better.
but I personally prefer the multipe arg one...
It depends... do you want to do this whenever you call it

Code: Select all

struct triple nums;
nums.a = 3;
nums.b = 4;
nums.c = 5;
int is = IsPythagoreanTriple( &nums );
or this?

Code: Select all

int is = IsPythagoreanTriple( 3, 4, 5 );
My 2c...

(And yes, templates would actually be quite powerful in kernel code, if they were used correctly...)
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post by Solar »

I'll skip the discussion, and just answer the original post.

Yes, that's pretty standard style (and I just assume that you pass pointers to structs, not the structs themselves).

Another pretty "standard" way of passing parameters is a "tag list". You declare your function taking variable arguments - foo( ... ) - and then pass key / value pairs (keys usually taken from an enum), with a special key designating end-of-parameters:

foo( MIN_WIDTH, 200, MAX_HEIGHT, 800, END );

Credit goes to AmigaOS where I saw this first. Good when you have a huge number of possible values, but usually want to change only very few of them from their defaults. It also had some other advantages I have since forgotten... 8)

Any well-written C code is next to trivial to "translate" to C++. Remember you don't have to use any of the "extra features" of C++, you can introduce them into existing code gradually.

As for your paranoia, for one global variables can be side-effected on in some subroutine where you aren't aware of the change (Bad Thing (tm)), and they make your code non-reentrant (i.e., if two threads work on the same code, they influence one another in non-deterministic ways - Bad Thing (tm)).
Every good solution is obvious once you've found it.
Tyler
Member
Member
Posts: 514
Joined: Tue Nov 07, 2006 7:37 am
Location: York, England

Post by Tyler »

hckr83 wrote:

Code: Select all

struct{
  unsigned int a,b,c;
}triple;
I hate to sound like an idiot, but i have never understood structs. In order to create a structure named triple, shouldn't your code be "struct triple {...". I thought placing names at the end of the struct declared variable of that type?
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post by Solar »

No, Tyler, you're absolutely right. I didn't really read the code, or I would have complained, too.

Code: Select all

struct foo_t
{
    int a;
    int b;
} bar;

struct foo_t baz;
You now have two structs of type struct foo_t, named bar and baz.
Every good solution is obvious once you've found it.
Tyler
Member
Member
Posts: 514
Joined: Tue Nov 07, 2006 7:37 am
Location: York, England

Post by Tyler »

Solar wrote:No, Tyler, you're absolutely right. I didn't really read the code, or I would have complained, too.

Code: Select all

struct foo_t
{
    int a;
    int b;
} bar;

struct foo_t baz;
You now have two structs of type struct foo_t, named bar and baz.
Oh, well i am glad i am not going mad. Structs, especially ones mixed with typedef have always confused me considerably.
Post Reply