작은숲:위키노트/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 &lt 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

이 작은숲 문서의 출처는 위키노트의 위키노트/C and C++ Coding Style 문서입니다.