순수 C(C++ 아님)에 대한 코딩 표준
저는 자바 배경(CS 수업에서)과 C++ 한 학기 출신입니다.저는 제 Co-Op을 위한 OpenCV 프로젝트를 막 끝내고 있는데 순수한 C로 되어 있어서 이 질문을 하기가 좀 늦었습니다.
순수 C의 설계 과정과 코딩 기준은 무엇입니까?
저는 객체 지향 프로그래밍, 설계 및 모범 사례를 잘 알고 있습니다.나는 C처럼 객체 지향적이지 않은 언어에 막막할 뿐입니다.모든 변수와 함수는 전역적인 것으로 나타납니다.정말 엉망진창으로 느껴져요.
저는 C에 대한 전문적인 경험이 없으므로(C++에서만), 제 조언, 트릭 및 팁은 "객체 중심"이므로 너무 심각하게 받아들이지 마십시오.
거의 물체 C?
기본적인 객체와 유사한 기능을 쉽게 시뮬레이션할 수 있습니다.
머리글에서 앞으로 유형을 선언하고 defit을 입력한 다음 "methods"를 선언합니다.예를 들어,
/* MyString.h */
#include <string.h>
/* Forward declaration */
struct StructMyString ;
/* Typedef of forward-declaration (note: Not possible in C++) */
typedef struct StructMyString MyString ;
MyString * MyString_new() ;
MyString * MyString_create(const char * p_pString) ;
void MyString_delete(MyString * p_pThis) ;
size_t MyString_length(const MyString * p_pThis) ;
MyString * MyString_copy(MyString * p_pThis, const MyString * p_pSource) ;
MyString * MyString_concat(MyString * p_pThis, const MyString * p_pSource) ;
const char * MyString_get_c_string(const MyString * p_pThis) ;
MyString * MyString_copy_c_string(MyString * p_pThis, const char * p_pSource) ;
MyString * MyString_concat_c_string(MyString * p_pThis, const char * p_pSource) ;
각 함수에는 접두사가 붙어 있습니다.다른 코드와 충돌하지 않도록 하기 위해 "구조"의 이름을 선택합니다.
OO같은 아이디어를 유지하기 위해 p_pThis를 사용했다는 것도 알게 될 것입니다.
소스 파일에서 유형을 정의하고 함수를 정의합니다.
/* MyString.c */
#include "MyString.h"
#include <string.h>
#include <stdlib.h>
struct StructMyString
{
char * m_pString ;
size_t m_iSize ;
} ;
MyString * MyString_new()
{
MyString * pMyString = malloc(sizeof(MyString)) ;
pMyString->m_iSize = 0 ;
pMyString->m_pString = malloc((pMyString->m_iSize + 1) * sizeof(char)) ;
pMyString->m_pString[0] = 0 ;
return pMyString ;
}
/* etc. */
"private" 함수(또는 private global variables)를 원할 경우, C 소스에서 static으로 선언합니다.이렇게 하면 외부에 보이지 않게 됩니다.
static void doSomethingPrivate()
{
/* etc. */
}
static int g_iMyPrivateCounter = 0 ;
상속받으려면 거의 망하는 거지변수를 포함하여 C의 모든 것이 전역적이라고 생각했다면 상속을 어떻게 모의할 수 있는지 생각하기 전에 C에 대한 경험을 더 쌓아야 합니다.
기타 팁
다중 코드 경로는 피합니다.
예를 들어, 여러 번의 반환은 위험합니다.예를 들어,
void doSomething(int i)
{
void * p = malloc(25) ;
if(i > 0)
{
/* this will leak memory ! */
return ;
}
free(p) ;
}
비정규 전역 사용 안 함
여기에는 (정적 함수가 아닌) "정적" 변수가 포함됩니다.
전역 비정규 변수는 거의 항상 나쁜 생각입니다(예: CAPI strtok에서 crappy 함수의 예를 참조). 다중 스레드 안전 코드를 생성하는 경우 처리하기가 어렵습니다.
이름 충돌 방지
함수 및 정의에 사용할 "이름 공간"을 선택합니다.이것은 다음과 같습니다.
#define GROOVY_LIB_x_MY_CONST_INT 42
void GroovyLib_dosomething() ;
주의 정의
C에서는 정의를 피할 수 없지만 부작용이 있을 수 있습니다!
#define MAX(a, b) (a > b) ? (a) : (b)
void doSomething()
{
int i = 0, j = 1, k ;
k = MAX(i, j) ; /* now, k == 1, i == 0 and j == 1 */
k = MAX(i, j++) ; /* now, k == 2, i == 0 and j == 3, NOT 2, and NOT 1 !!! */
}
변수 초기화
변수를 초기화하지 않고 선언하지 않도록 합니다.
int i = 42 ; /* now i = 42 */
int j ; /* now j can have any value */
double k ; /* now f can have any value, including invalid ones ! */
초기화되지 않은 변수들은 고통스러운 버그의 원인입니다.
모든 C API를 알고 있습니다.
K&R에 나와 있는 CAPI 기능 목록은 상당히 적은 편입니다.20분 안에 전체 목록을 읽으실 수 있을 겁니다.당신은 그 기능들을 알고 있어야 합니다.
경험 좀 해볼래요?
C API를 다시 작성합니다.예를 들어 string.h 함수의 버전을 직접 작성하여 어떻게 수행되는지 확인해 보십시오.
함수 또는 개체의 범위를 소스 파일의 로컬로 지정하려면 "static"으로 선언해야 합니다.그것은 조금 도움이 됩니다.
그렇지 않으면 네임스페이스 충돌을 피할 수 있는 일반적인 관용구는 이름에 일종의 시설 식별자를 넣는 것입니다.예를 들어, foo.c의 모든 것은 foo_*로 명명될 수 있습니다.
좋은 소식은 C에서 반객체 지향 방식으로 프로그래밍할 수 있다는 것입니다.데이터 보호, 접근 기능 노출 등을 할 수 있습니다.C++의 모든 환상을 가지고 있는 것은 아닐지 모르지만, 제가 다른 사람들의 C++ 코드를 본 바로는, 어쨌든 많은 사람들이 그 환상을 사용하지 않습니다.즉, 사람들은 클래스 안에 C 코드를 적는데, C에서는 클래스 컨테이너 없이 동일한 코드를 적습니다.
우선 C프로그래밍과 스타일에 관한 책을 읽으세요, K&R도 괜찮습니다.둘째, CERT Programming Standard를 확인해 보는 것을 추천합니다.이 사이트는 주로 "보안" 코딩 표준에 초점을 맞추고 있지만, 대부분의 콘텐츠는 모두가 따라야 할 일반적인 코드 품질 표준입니다.여기에 언급된 것들을 수행하면 품질이 향상되고, 성가신 버그를 제거할 수 있으며, 부작용으로 코드를 더욱 안전하게 만들 수 있습니다.
순수 C로 객체 지향 설계를 할 수 있습니다.입니다.class
을 필요로 으로.this
첫 번째 매개 변수는합니다.
가 .class
가 name며로 ,이며static
은 .malloc()
메모리와 데이터 필드의 명시적인 초기화를 가져옵니다.
개인 () 를)를 할 수 .void *
짝수 또는 형식 안전이 필요한 경우 불완전한 형식의 포인터로 사용).다에 struct
잘 통합니다.
이 패턴 뒤에는 여러 라이브러리가 뒤따릅니다.초기화 함수는 모든 라이브러리 메서드에 전달해야 하는 쿠키를 반환하고 하나의 메서드는 소멸자 역할을 합니다.
물론 순수한 C에서 디자인을 잘 할 수 있는 다른 방법들도 있지만, OOO가 당신을 위해 일한다면 그것을 완전히 버릴 필요는 없습니다.
파일 범위 변수와 함수를 각각의 소스 파일로 표시하는 것을 제한할 수 있습니다(그러나 이러한 개체에 대한 포인터를 전달하는 것을 방지하지는 못합니다).
예를 들어,
/** foo.c */
static void foo_helper() {...} /* foo_helper cannot be called by name
outside of foo.c */
static int local_state; /* local state is visible at file scope,
but is not exported to the linker */
언급URL : https://stackoverflow.com/questions/1262459/coding-standards-for-pure-c-not-c
'programing' 카테고리의 다른 글
Oracle 자동 요일별 파티셔닝 (0) | 2023.09.28 |
---|---|
WP 게시글 제출을 위한 오프라인 양식 작성 방법 (0) | 2023.09.28 |
오류 [ERR_]PACKAGE_PATH_NOT_EXPORTED]: 패키지 하위 경로 './lib/tokenize'가 패키지의 "exports"에 의해 정의되지 않았습니다.node_에서 모듈의 json (0) | 2023.09.28 |
MySQL에서 현재 UTC 시간에 대한 Unix 타임스탬프를 가져오는 가장 좋은 방법 (0) | 2023.09.28 |
MySQL LIMIT X, X를 늘리면 Y가 느려집니다. (0) | 2023.09.23 |