임베디드 개발(before)/IoT 임베디드 SW 개발자 양성과정

내가 보려고 정리해둔 C언어

주운녕 2020. 7. 21. 23:08

goorm이란 사이트에서 C언어를 혼자 공부하며 정리한 내용입니다.(edu.goorm.io)


1. double형은 scanf 입력받을 때는 "%lf" 로만. (실수 출력은 "%f"로만)

2. 자료형 명칭, 크기 기억하기

자료형 명칭, 크기

3. 변수 앞에 const 붙이면 상수 된다. => 안정성을 위해 사용 //선언과 동시에 초기화하기

(ex. const double PI = 3.141592)

4. float형은 정의할 때 [ float a = 0.35f ] 와 같이 'f' 를 붙여준다. => 기본적으로 실수는 double형으로 인식해서.

5. printf("%d", a>1)  => a>1 이 참이면 '1' 출력

6. XOR 연산은 두 bit가 같지 않을 경우만 1 

7. 비트 이동 << , >> 를 사용하여 *2^n 연산 대체 가능. (but 자료형 고려, unsigned 안 하면 음수 처리되어 보수연산 하게 된다. (MSB까지 닿을 경우))  (>>시 cpu마다 MSB채우는 값이 다름.(보통 음수였음 음수유지))

8. unsigned char 입력받을 때는 %hhu 사용 (별로 안중요)

9. 문자열 배열 입력 시 배열의 이름이 주소를 담고 있어서 scanf 사용할 때 배열에 &안 붙여도 됨.(ex. scanf("%s", str);)

10. break은 반복문 바로 빠져나오기, countinue는 바로 다음 반복문 실행

 

-함수

11. 함수 원형은 main위에 선언, 정의는 main문 아래에 하는 습관

12. 지역변수는 중괄호 영역 내에서만 사용

       전역변수는 어느지역에서나 사용가능 (프로그램 종료될 때까지 존재), 초기화 안해도 쓰레기값 대신 '0'으로 자동 초기화

13. 전역변수 너무 많이 쓰면, 어떤 함수에서 전역변수 값을 바꾸는지 알기 어려워지고, 특히 코드가 길어질수록 지역변수와 이름이 겹칠 가능성이 높아진다. 그럴 경우 지역변수로 우선 접근된다. 또한 프로그램 종료까지 메모리 잡아먹음 => 되도록 지역변수를 쓰는 습관

 

-포인터

14. 포인터는 변수의 주소 값을 저장한다.

15. 그냥 포인터에 저장된 주소를 불러올 때는 p로, 포인터에 저장된 [ 주소 값 내부의 값 ]을 불러올 때는 *p로

       선언은 [int*  p], [int  *  p], [int  *p] 모두 된다.

16. 포인터 변수의 크기는 32bit 시스템이면 4byte ,  64bit 시스템이면 8byte 크기를 가진다. => 명시하는 자료형(int, char)은 단지 가리킬 주소가 어떤 자료형을 갖는지 알려주기 위함이다. (가리키는 변수에 맞춰 포인터 변수도 자료형을 맞춰준다.

17. 포인터는 주소 값을 담는 변수이기 때문에 어떤 특정한 숫자로 초기화할 수 없다. 따라서 쓰레기 값이 들어가지 않도록 되도록이면 NULL(0)로 초기화하는 것을 권장한다.

18. 참조 연산자 " * " 는 포인터의 이름이나 주소 앞에 사용, 포인터가 가리키는 주소에 저장된 값을 반환한다.

19. *p => p에 저장된 주소 값이 가리키는 변수, 그 안에 저장된 데이터를 불러온다. (*p => p에 저장된 주소 값을 "*"(참조) 하겠습니다.)

20. 참조 연산자와 증감 연산자 사용 시 주의!! [증감연산자(++)가 참조연산자(*)보다 우선순위가 높다!!]

ex) (*p)++ (O)

       *p++   (X) => *(주소값) 한번 후, 주소값+1을 한다는 의미.

21. 포인터의 진가 : 함수사용 시 굳.

함수 사용시 포인터로 메모리의 주소를 넘겨주면 함수에서도 메모리에 직접적으로 참조할 수 있기 때문에, 변숫값을 바로 수정하는 것이 가능하다. (지역변수의 단점 극복!)

22. [Call by Value 방식] : 함수에서 값을 복사해서 전달하는 방식. 인자로 전달된 변수와는 별개의 변수가 됨 (별개의 지역변수) => 원본 값 (main문 안의 변수 값)을 바꿀 필요가 없을 경우, 이 방식을 사용한다.

23. [Call by Reference 방식] : 함수에서 주소 값을 전달하는 방식.

-> 엄밀히 따지면 C언어는 주소값 자체를 Call by Value 방식으로 넘겨줌으로 Call by adress 방식이라 할 수 있다. (포인터를 이용해 Call by Reference를 구현한 것.)

24. 배열의 주소는 연속되어 있고, 배열의 이름은 첫 번째 요소의 주소 값을 나타낸다. 즉 포인터 변수와 같은 기능을 한다. => scanf 로 입력받을 시 문자열(배열) 은 &를 안 붙여도 된다.

25. 포인터 변수에 n만큼 더하거나 뺄 때 자료형 크기*n 만큼 증감한다

=> int *p = arr; // p==10640    ->    p+1 == 10644      ==> int형 4byte만큼 증가됨.

26. 포인터 상수화

1) int* const ptr -> 포인터 변수의 상수화 == 저장되는 주소 값을 상수화 

ex) ptr=&num  ->  ptr=&num2로 변경 불가  // *ptr =10  -> *ptr=20 과 같이 간접참조연산을 이용한 데이터는 변경 가능

 

2) int const *ptr == const int* ptr -> 변수가 가리키는 주소가 가진 데이터를 상수화

ex) int num = 10;    const int * ptr = &num 일 때 // num=20 은 가능하지만 *ptr=20은 불가능!

      (=> num 변수 자체가 상수가 된 것이 아니라, 포인터를 이용해 데이터 변경하는 것을 막음.)

 

27. const int * const ptr 다른 변수(주소 값)를 저장하는 것도, 참조 연산자를 통해 데이터를 변경하는 것도 불가능.

28. 이중 포인터 : (변수의 주소(&num) 를 저장하는 (포인터 변수(ptr)의 주소(&ptr))를 저장하는 변수(pptr)

=> *(*pptr) = *(*&ptr) = *ptr = *(&num) = num

29. 이중 포인터는 포인터의 주소 값을 담는 주소를 바꾸거나 "함수에서 문자열을 바꿀 때" 사용

30. 포인터 배열 : 주소 값들을 저장할 수 있는 배열! (int *pt[5])

 

- 구조체

31. 구조체 : 하나 이상의 변수를 묶어서 좀 더 편리하게 사용 돕는 도구

Struct student{
	int id;
};
int main(){
	struct student goorm = { .age=20, .phone_number = "010"};
//(=int 같은 자료형) (=변수명) = { .age=20, .phone_number = "010"};

32. typedef 사용 - 자료형을 새롭게 이름 붙일 때 쓰는 키워 조체 정의 시 중괄호 뒤에 구조체 별칭을 써준다.

구조체 다양한 정의 방식

33. 구조체 포인터 : struct student *ptr

                       (=int처럼 '자료형'으로 보고) 구조체가 아닌! 구조체 타입의 주소를 저장하는 변수!

34. 구조체 포인터 응용 방식

typedef struct {
	int age;
	...
}student;

int main(void){
	student goorm;
	student *ptr;
	ptr = &goorm;
	(*ptr).age = 20;	//ptr -> age = 20 으로 표현할 수 있다!

35. 중첩 구조체 : 구조체 멤버 안에 다른 구조체가 포함됨. => 여러 가지 정보를 관리하기에 용이.

ex) 담임쌤의 정보를 학교 학생마다 넣을 때 : 학생 구조체 안에 선생 구조체

36. 자기 참조 구조체 => '연결 리스트'나 '트리'를 만들 때 사용(자료구조)

typedef struct{
	char name[15];
    int age;
    struct Student *ptr;  //구조체에선 자기자신을 가리키는 포인터를 멤버로 가질 수 있다. 
} Student;					//어떤 정보를 저장하는 것이 아닌, 그냥 자기 가리킴.

37. 코드가 길어질수록 함수로 분리하는 것이 좋다.

38. 포인터 사용하지 않으면 매개변수에 복사되는 거라 원본 값은 수정 안되고 복사 공간으로 공간 낭비 --> 비효율적.

따라서 포인터 + 함수를 활용하여 call by reference 방식처럼 값을 바꿔주어야 한다.

39. 포인터 + 구조체 + 함수 예제

 

추가로 공부할 부분

  • C언어 고급편
  • C언어로 배우는 자료구조
  • 알고리즘

* 개인적으로 공부한 내용을 정리한 게시글이기 때문에 잘못된 정보가 있을 수 있습니다.