작은숲:위키노트/C and C++ Coding Style: 두 판 사이의 차이
잔글 (문자열 찾아 바꾸기 - "{{퍼온문서|위키노트|{{#invoke:string|replace|위키노트:|}}}}분류:위키노트에서 가져온 문서" 문자열을 "{{퍼온문서|위키노트|{{#invoke:string|replace|{{PAGENAME}}|위키노트:|}}}}분류:위키노트에서 가져온 문서" 문자열로) |
잔글 (Utolee90님이 C and C++ Coding Style 문서를 작은숲:위키노트/C and C++ Coding Style 문서로 이동했습니다: 제목 변경) |
||
| (같은 사용자의 중간 판 2개는 보이지 않습니다) | |||
| 327번째 줄: | 327번째 줄: | ||
</pre> | </pre> | ||
<tt>Copyright (c) 1999 By C Scene. All Rights Reserved. http://www.cscene.org</tt> | <tt>Copyright (c) 1999 By C Scene. All Rights Reserved. http://www.cscene.org</tt> | ||
[[분류:공유]] | [[분류:위키노트/공유]] | ||
[[분류:C 언어]]{{퍼온문서|위키노트|{{#invoke:string|replace|{{PAGENAME}}|위키노트:|}}}}[[분류:위키노트에서 가져온 문서]] | [[분류:C 언어]]{{퍼온문서|위키노트|{{#invoke:string|replace|{{PAGENAME}}|위키노트:|}}}}[[분류:위키노트에서 가져온 문서]] | ||
2022년 5월 7일 (토) 13:08 기준 최신판
_Secret
http://www.nauticom.net/www/secret
programming@teo.nauticom.net
C and C++ Coding Style
This was written in order to show new C and C++ coders the coding style
that I use and prefer. It also contains explanations of why I use some of the
techniques that I will show you. Other people's styles vary (Of course, I
think most other styles are crap) but this is my preferred style. Use it if
you like it or don't use it.
First Note: use ONLY /* */ comments in C and use // comments in C++. This
is a bit organized and makes the programs look cleaner. not all C compilers
allow // comments, so you're just making your program more portable for not
using them. In C++, I wouldn't use /* */ since they would make the code
uglier.
At the top of every program, header, resource or any source code I place
a block comment with the intent of the file.
in C:
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*
| This is an Example |
| |
| |
| Place Dates, Compiling Info, Contact Info |
| Purpose of program |
*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
in C++:
/////////////////////////////////////////////////////////////
// This is an Example //
// //
// Place Dates, Compiling Info, Contact Info //
// //
// Purpose of Program //
/////////////////////////////////////////////////////////////
Next come the header files, I usually like to have them 1 space from the side
of the file like:
C++:
//////////////////
// Header Files
//////////////////
#include <iostream.h>
C:
/* Header Files */
#include <stdio.h>
Like the above, except some old C compilers will not compile any code with a
header file like this, they require all preprocessor commands to be 0 spaces
from the side.
Like so:
C:
/* Header Files */
So, you decide your platform and style if you should have 1 space or 0 space.
Next, come the constants and structures
C++:
/////////////////////////////
// Constants and Structures
/////////////////////////////
const int MAX_X = 10;
const int MAX_Y = 20;
C:
/* Constants and Structures */
#define MAX_X 10
#define MAX_Y 20
I always have constants in ALL CAPITAL LETTERS this makes them easier to notice
in the program.
Structures should always be typedefs.
typedef struct pixel_type {
char Color;
int X, Y;
} Pixel;
And have that form. With the first bracket on the same line as the struct. I
like to give structures Capital first letters.
Next, come the global variables (If any). In windows, it is necessary to use
Globals and when implementing interrupt handlers in DOS. Other than that, if
you do not have to use a global, do not ever use globals. Try to use as few as
possible.
C++:
/////////////////////
// Global Variables
/////////////////////
Pixel g_Screen[64000];
C:
/* Global Variables */
Pixel g_Screen[64000];
Globals should begin with a "g_" so they are easier to point out. And the
first name should begin with a capital letter.
Next, in C++ come the Object defines.
////////////////////
// Objects
////////////////////
////////////
// Foo Object
////////////
class Foo {
public:
private:
} ;
The brackets I like to take on the same style as the 0 and I like to have the
public first, then the private. When you're going to use a class, You'd want
to see the interface that you can use first, not the hidden implementations.
private goes second. Objects I like to have named with a capital first letter
as well.
Next, come the function prototypes.
C++:
//////////////////////////
// Function Prototypes
//////////////////////////
void Foo(void);
void RainMan(int, char *);
int Team(int [10][]);
C:
/* Function Prototypes */
void Foo(void);
void RainMan(int, char *);
int Team(int [10][]);
One space in, and any function with NO parameter should specify VOID. All
functions should be prototyped. No function should come before the main.
Prototypes give you a quick reference list of what functions the program uses
and what parameters they take. Easier and quicker to look at a ref list like
the above than to have the whole place jammed with all of the functions. Also,
about 0 void, this is for ANSI-compliant C compilers.
In the Old K&R C, you just had to list the name of the function, which looked
like:
int Foo();
void RainMan();
int Team();
So, in order to clarify everything, I would list the parameter types (Even
void, that's an implied "int" but it's just ignored when you don't use it), but
I would NOT list the variable names, they are irrelevant. Only list the types.
Next comes the main function.
C++:
/////////////////////////////
// Main Function
/////////////////////////////
int main(void)
{ ...
return 0;
}C:
/* Main Function */
int main(void)
{ ...
return 0;
}I would indent the function 1 space and have the { ALWAYS on the following line
and NOT indented. Where CODE is concerned, NEVER put { on the same line as
anything else. They should always be on the next line and lined up with the
previous one. This is for easier following logic and 0/ending blocks.
MAIN should ALWAYS return an int. Too many people are defining main as void
and the operating system will return a value no matter what. 0 "int" just
ensures that it doesn't return garbage.
This is retarded:
int main(void) {
}"It's too hard to see logic when it's unlogical!"
The ONLY time in code that { can be on the same line is:
do {
...
} while(x < 0) ;
And that is because it has beginning and ending words (do/while) so the do { is
treated as the { and the } while is treated as the }.
Any code block consisting of 1 instruction should not use {'s.
This is dumb:
if(x == y)
{
return 0;
}
else
{
return 1;
}
This is smart:
if(x == y)
return 0;
else
return 1;
There is no reason to use { } unless you have more than 2 statements, OR have
an if within an if-else:
if(x == y)
{ if(z == t)
return 0;
}else
return 1;
In the above case, the {'s } are necessary since you want the else associated
with the first if. If you want it with the second if, the following is good:
if(x == y)
if(z == t)
return 0;
else
return 1;
Declaring Pointers:
int* x;
int * x;
int *x;
Which one is the correct way? They all work, but what are the pros and cons?
int* x, y;
Having the * on the type makes you think that x and y are pointers. only x is.
The * isn't used on every variable declared, they must be separate:
int* x, *y;
so, <type>* is a bad idea, it is confusing.
int * x;
The above has the same idea. The * is floating.
int * x, * y;
It's a little "Spacey"
This is what I consider correct:
int *x;
You know the type is int and x is a pointer.
int *x, y;
You know x is a pointer and y is not, it's more obvious.
GOTO's
Now, everyone has been saying for a long time "GOTO's are Bad! Never use them!"
This is most likely true, but there are exceptions to this rule.
This doesn't come up often, but sometimes, SOMETIMES a goto is necessary.
SOMETIMES a GOTO isn't necessary, but it's a better alternative.
If you have to use a goto, remember these rules:
Rule #1 with a goto: NEVER JUMP BACKWARD. Jumping backward is the hardest code
to read,
you can easily replace this with a do { } while(); or other loop construct.
Rule #2 DO NOT JUMP FAR OR OUT OF THE FUNCTION! Don't jump functions or jump
too far from the goto, this starts to create messy and unreadable code.
Rule #3 Make your label jump names IN ALL CAPS and make them SELF EXPLANATORY
i.e. don't name them X or Y name them like EXIT_ON_BREAK:
Example of when goto is useful:
The best example of where GOTO is useful is in a big nested loop:
/* Advance Every Node */
for(x = 0; x < 100; x++)
for(y = 0; y < 100; y++)
for(z = 0; z < 100; z++)
if(Matrix[x][y][z])
goto COLLISION_EXIT;
else
Matrix[x][y][z]++;
COLLISION_EXIT:
Now, you see the above (a hypothetical case) when the Matrix entry is 0, a 0
has 0. Otherwise, we advance the point. Let's just say that we want to advance
this matrix unless a collision has 0, then we want to just exit and destroy
that matrix. You can use a flag, but as you see here:
/* Advance Every Node */
for(x = 0, Flag = FALSE; x < 100 && (Flag); x++)
for(y = 0; y < 100 && (Flag); y++)
for(z = 0; z < 100 && (Flag); z++)
if(Matrix[x][y][z])
Flag = TRUE;
else
Matrix[x][y][z]++;
The above is the alternative.
has to increment 3 memory locations, and perform 3 conditional tests.
When SPEED is of the essence, a GOTO can solve the problem, but these problems
do not come up a lot and this is not a license to code crap.
Spacing
for(;;)
for (;;)
I 0 the first, The second looks a little weird.
I also like to use ;'s and ,'s like you use them in English:
for(x = 1, y = 10; x < y; x++, y--) ;
Unless used in loops or classes
The above, I like to space ;'s out by 1 if it's representing a Loop or a struct
that's not typedef'ed. blah, SPACE blah I like to put spaces after ; and ,'s
in other normal use.
EVERY 0 OPERATOR SHOULD HAVE A SPACE ON BOTH SIDES!
x = 1;
NOT
x=1;
[ed. do you mean if(x == 1); NOT if(x==1);?]
I also like indents. The Indents I use are more relevant to how must[ed. ?]
nesting will occur.
If there is not much nesting, I will use 3-4 spaces. If a lot of nesting will
occur, depending, I will use 1-2 or 3 spaces. I try to keep the lines of code
fitting on the screen. Which means that in lines that extend over, you should
find a good midpoint to put on the next line, but you put them on the next line
INDENTED.
Another bit we must cover is void *'s.
MyThing = malloc(sizeof(char *)*20);
for(x = 0; x < 20; x++)
MyThing[x] = malloc(20);
The above code is crap. All void *'s should be typecast for the following reasons:
# Most compilers aren't completely standard. They have OS extensions on and
many will give a warning or error on not typecasting a void *. Especially
if sometime you have to compile it on a C++ compiler.
# More readable. MyThing = malloc(2); That could mean MyThing is a short *
or a char * depending on the system architecture.
# You should always check for allocation problems.
The correct code:
C:
/* Allocate Pointers */
if(!(MyThing = (char **)malloc(sizeof(char *)*20)))
{ printf("Not Enough Memoryn");
exit(0xFF);
}/* Allocate The Character Strings */
for(x = 0; x < 20; x++)
if(!(MyThing[x] = (char *)malloc(20)))
{
printf("Not Enough Memoryn");
exit(0xFF);
}
C++:
// Allocate Pointers
if(!(MyThing = new char *[20]))
{ cout << "Not Enough Memory" << endl;
exit(0xFF);
}// Allocate The Character Strings
for(x = 0; x < 20; x++)
if(!(MyThing[x] = new char[20]))
{
cout << "Not Enough Memoryn" << endl;
exit(0xFF);
}
NOTE: C++: "cout" can be replaced by "cerr" and
C: printf("") can be replaced by fprintf(stderr,"")
** For those who want to use standard error print out procedures. **
Declaring a function as "inline" is something that was brought into C++. As
you know though, if you do the following in a class:
// Class X
class x {
public:
x(void) { cout << "Initialize" ; }
} ;
x::x() will be inline. This I do not feel is nice coding, it mixes prototypes
with function definitions and makes a big mess. I feel that you should use
the keyword "inline".
// Class X
class x {
public:
inline x(void);
} ;
That way, you can easily switch functions from and to
inline without moving around code. Also, some people don't know that the top
version is inline, this way, it's explicitly shown.
The coding style listed above is only the opinion of the author, you can adapt
some of it or adapt all of it, it's left up to you how you think code should look.
Copyright (c) 1999 By C Scene. All Rights Reserved. http://www.cscene.org