혼자 공부하는 C언어 (2)

Erdos·2024년 10월 5일
0

감상

목록 보기
39/42
post-thumbnail

chapter5 선택문


5-1 if문

  • 분할 정복 기법(divide and conquer): 비교 항목이 많은 경우 if문을 여러 번 중첩해서 쓰면 실행 시간을 줄이는 데 도움이 된다. 하지만, 가독성은 떨어지므로 주의

5-2 if문 활용과 switch ~ case문

switch ~ case문

#include <stdio.h>

int main(void)
{
    int rank = 2, m = 0;
    
    switch(rank)
    {
    case 1:
        m = 300;
        break;
    case 2:
        m = 200;
        break;
    case 3:
        m = 100;
        break;
    default:
        m = 10;
        break;
    }
    printf("m : %d\n", m);
    return 0;
}
  • 규칙 1) 조건식으로 정수식만 사용해야 한다.
  • 규칙 2) 기본적으로 case는 break를 포함합니다.
    • 해당 블록을 탈출하는 데 사용한다.
    • 제한적으로 break를 생략해야 하며 생략할 때는 자세한 설명을 주석으로 남겨야 한다.

chapter6 반복문


6-1 while문, for문, do ~ while문

do ~ while문

  • 한번도 안 써봤다!
    일단 반복할 문장을 수행한 후에 조건 검사

6-2 반복문 활용

break와 continue 분기문

  1. break로 무한 반복문 빠져나오기
    무한 반복문
while(1)
for (;;)
  1. continue
    반복문의 일부를 건너뛴다.

개인적으로 while문을 작성할 때, 무한루프에 자주 빠지는데 간단한 예제 하나

#include <stdio.h>

int main(void)
{
    int i;
    int sum = 0;
    while(i <= 100)
    {
        if ((i % 3 ) == 0)
        {
            i++; // 이거 없으면 무한루프!
            continue;
        }
        sum += i;
        i++;
    }
    printf("%d", sum);
}

chapter7 함수


7-1 함수의 작성과 사용

함수 선언

함수 선언은 컴파일러가 새로 만든 함수를 인식할 수 있도록 알리는 역할을 한다.
그래서, 함수 선언이 없으면 함수 정의는 항상 함수 호출 이전에 있어야 한다.

#include <stdio.h>
int ft_str_is_numeric(char *str); 
//prototype 
// 이걸 쓰지 않을거라면, ft_str_is_numeric이 상단으로 배치되어야 한다.

int main(void)
{
  printf("%d\n", ft_str_is_numeric("asdfasdf"));
  printf("%d\n", ft_str_is_numeric("ASDFasdf"));
  printf("%d\n", ft_str_is_numeric("ASSDDGBZAQ"));
  printf("%d\n", ft_str_is_numeric("asdf1145aa"));
  printf("%d\n", ft_str_is_numeric("11aaaaaa11"));
  printf("%d\n", ft_str_is_numeric("2745555511"));
  printf("%d\n", ft_str_is_numeric("     "));
    return 0;
}

int	ft_str_is_numeric(char *str)
{
	while (*str != '\0')
	{
		if (!(*str >= '0' && *str <= '9'))
			return (0);
		str++;
	}
	return (1);
}

chapter8 배열


8-1 배열의 선언과 사용

  • sizedof 연산자를 활용한 배열 처리

    sizeof(배열명) / sizeof(배열 요소)

8-2 문자를 저장하는 배열

char형 배열 선언 시 주의할 점
1. 배열의 크기는 최대한 넉넉하게 선언한다.
2. 배열 요소의 개수는 최소한 '문자열 길이 + 1' 이어야 한다 => 끝에 '\0'

문자열 대입

strcpy 함수 구현하기

#include <stdio.h>

char *ft_strcpy(char dest[], char src[]);

int main(void)
{
	char src1[] = "Hello, World!";
	char src2[] = "C programming";
	char dest1[50]; // 목적지 버퍼는 원본보다 충분히 커야 함
	char dest2[50];

	// 첫 번째 문자열 복사
	ft_strcpy(dest1, src1);
	printf("Source:      \"%s\"\n", src1);
	printf("Destination: \"%s\"\n\n", dest1);
}

char *ft_strcpy(char *dest, char *src)
{
    char *origin;
    
    while (*src)
    {
        *dest = *src;
        src++;
        dest++;
    }
    *dest = '\0';
    return origin;
}

문자열 끝에 널 문자가 없다면?

쓰레기 값이 남아서 함수의 결과를 예상할 수 없다. 그러니 꼭 널 문자 저장!

chapter9 포인터


9-1 포인터의 기본 개념

  1. swap 함수 구현하기
#include <stdio.h>

void ft_swap(int *a, int *b);

int main(void)
{
    int a;
    int b;
    
    a = 1;
    b = 3;
    ft_swap(&a, &b);
    
    printf("a = %d\n", a);
    printf("b = %d\n", b);
}

void ft_swap(int *a, int *b)
{
    int temp;
    
    temp = *a;
    *a = *b;
    *b = temp;
}
  • '*' = 간접 참조 연산자: 포인터가 가리키는 변수를 사용할 때 포인터에 사용하는 특별한 연산자
  • '&' = 주소 연산자: 변수의 주소를 구할 때 사용하는 연산자
  1. const를 사용한 포인터
    const 예약어를 포인터에 사용하면 가리키는 변수의 값을 바꿀 수 없다는 의미다.
#include <stdio.h>

int main(void)
{
    int a = 10, b = 20;
    const int *pa = &a; // 포인터 pa는 변수 a를 가르킨다
    
    printf("변수 a 값: %d\n", *pa); // 포인터를 간접 참조해 a 출력
    pa = &b; // 포인터가 변수 b를 가리키게 한다.
    printf("변수 b 값: %d\n", *pa); // 포인터를 간접 참조해 b값 출력
    pa = &a; // 포인터가 다시 변수 a를 카리킨다.
    a = 20; // a를 직접 참조해 값을 바꾼다
    printf("변수 a 값:%d\n", *pa); // 포인터로 간접 참조해 바뀐 값 출력
    return 0;
}

포인터에 const를 사용하는 대표적인 예는 문자열 상수를 인수로 받는 함수.
-> 값이 바뀌면 안 되므로 매개변수를 통해서 값을 바꿀 수 없도록 매개변수로 선언된 포인터에 const를 사용한다. 12장에 내용이 나올거라고 함.. 🤔

9-2 포인터 완전 정복을 위한 포인터 이해하기

주소와 포인터의 차이

  • 주소: 변수에 할당된 메모리 저장 공간의 시작 주소 값 자체. 상수
  • 포인터: 그 값을 저장하는 또 다른 메모리 공간(값이 바뀔 수 있음). 변수

주소와 포인터의 크기

포인터의 대입 규칙

  • 포인터는 크기가 모두 같다.
  1. 포인터는 가리키는 변수의 형태가 같을 때만 대입해야 한다.
#include <stdio.h>

int main(void)
{
    int a = 10;
    int *p = &a;
    double *pd;
    
    pd = p;
    printf("%lf\n", *pd);
    
    return (0);
}

GDB에서는 책과는 조금 다른 아래와 같은 결과 출력

왜 이렇게 나왔나?

  • 참고자료 1)
  • 참고자료 2) IEEE 754 -> 한 번 훑어보기

  1. 형 변환을 사용한 포인터의 대입은 언제나 가능하다.

포인터를 사용하는 이유

  • 메모리를 직접 접근하는 경우
  • 동적 할당한 메모리를 사용하는 경우 반드시 필요하다.
profile
수학을 사랑하는 애독자📚 Stop dreaming. Start living. - 'The Secret Life of Walter Mitty'

0개의 댓글