c 공부 2024.03.27
gpt
커스텀 모드가 존재, 내 정보를 주면 줄 수도 내게 맞는 더 디테일 한 답변을 줌
포인터
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h> // 표준 입출력 함수들을 사용하기 위한 헤더 파일 포함
int main() // 메인 함수 시작
{
// 변수 선언
char ch; // 'char' 타입의 변수 'ch' 선언
int in; // 'int' 타입의 변수 'in' 선언
double db; // 'double' 타입의 변수 'db' 선언
// 포인터 변수 선언 및 초기화
char *pc = &ch; // 'ch'의 주소를 저장하는 'char' 타입의 포인터 변수 'pc'
int *pi = ∈ // 'in'의 주소를 저장하는 'int' 타입의 포인터 변수 'pi'
double *pd = &db; // 'db'의 주소를 저장하는 'double' 타입의 포인터 변수 'pd'
// 각 변수의 주소 크기 출력
printf("char형 변수의 주소 크기 : %d\n", sizeof(&ch)); // 'ch'의 주소의 크기를 출력
printf("int형 변수의 주소 크기 : %d\n", sizeof(&in)); // 'in'의 주소의 크기를 출력
printf("double형 변수의 주소 크기 : %d\n", sizeof(&db)); // 'db'의 주소의 크기를 출력
return 0; // 프로그램 종료
}
포인터를 완전히 이해하지 못하면 C 언어를 사용할 줄 안다고 할 수 없을 정도로 포인터는 매우 중요. 한편 많은 사람이 숨을 헐떡이며 넘어가는 구간.
이거 뭐 쓰는데 이거 뭐야 이런 의문이 중요함 이걸 chat gpt에게 물어봐서 어떻게든 비어잇는 지식을 채우기
아래 코드는 형변환이 필요하다는것을 알리기 위한 목적으로 작성
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
int a = 10;
int *p = &a;
double *pd ;
pd = p;
printf("%lf\n", *pd);
return 0;
}
float vs. double
메모리 크기와 정밀도:
float: 32비트(4바이트)의 메모리를 사용하며, 대략 7자리의 정밀도.
double: 64비트(8바이트)의 메모리를 사용하며, 약 15~16자리의 정밀도.
범위:
float: 대략 1.4E-45에서 3.4E+38까지의 범위를 표현.
double: 약 4.9E-324에서 1.8E+308까지의 더 넓은 범위를 표현.
사용 상황:
float: 메모리를 절약해야 하거나 메모리 대역폭이 중요한 경우에 사용. 예를 들어, 임베디드 시스템이나 모바일 애플리케이션에서 유용.
double: 더 높은 정밀도가 필요한 과학적 계산이나 공학적 계산에서 주로 사용.
성능:
일부 시스템에서는 double 연산이 float 연산보다 느릴 수 있지만, 현대의 많은 컴퓨터 시스템은 double 연산을 최적화하여 비슷한 속도로 실행할 수 있음.
종합하면, 데이터 타입 선택은 애플리케이션의 요구사항과 환경에 따라 달라지며, 정밀도와 메모리 사용량을 고려하여 적절한 타입을 선택해야 함.
함수
함수가 위에잇으면 함수를 선언 안해도 되는데 밑에 함수를 넣을거면 함수를 미리 선언 해줘야함
함수 위
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
void swap(int *pa, int *pb)
{
int temp;
temp = *pa;
*pa = *pb;
*pb = temp;
}
int main(void)
{
int a = 10, b = 20;
swap(&a, &b);
printf("a:%d , b:%d\n",a, b);
return 0;
}
함수 아래
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
void swap(int *pa, int *pb);
int main(void)
{
int a = 10, b = 20;
swap(&a, &b);
printf("a:%d , b:%d\n",a, b);
return 0;
}
void swap(int *pa, int *pb)
{
int temp;
temp = *pa;
*pa = *pb;
*pb = temp;
}
C 언어에서 함수를 정의하는 위치는 여러 가지 스타일과 선호도에 따라 달라질 수 있으며, 각각의 방식은 특정 상황에서 장단점을 가집니다. 주요 고려사항은 코드의 가독성, 유지보수성, 그리고 컴파일 과정의 용이성입니다.
함수를 main
함수보다 위에 두는 경우:
장점:
- 함수 정의가
main
함수나 다른 함수들보다 먼저 나오기 때문에, 별도의 함수 선언(프로토타입) 없이도 해당 함수들을 사용할 수 있습니다. 이로 인해 코드가 간결해질 수 있다. - 코드를 위에서 아래로 순차적으로 읽을 때, 함수의 구현을 먼저 볼 수 있으므로, 함수의 동작 방식을 이해한 후
main
함수나 다른 함수들에서의 사용 방식을 볼 수 있다.
단점:
- 큰 프로젝트에서 많은 함수들이
main
함수보다 위에 위치하게 되면, 프로그램의 진입점인main
함수를 찾기 위해 많은 스크롤을 해야 할 수 있다. 이는 가독성을 저하시킬 수 있음.
함수를 main
함수 아래에 두는 경우:
장점:
- 프로그램의 진입점인
main
함수를 파일의 상단에 위치시킬 수 있고, 프로그램의 구조와 흐름을 빠르게 파악할 수 있다. 이는 특히 큰 프로젝트나 복잡한 프로그램에서 유용하다. main
함수에서 호출되는 함수들의 관계를 순차적으로 나열할 수 있어, 프로그램의 로직을 이해하기 쉽게 만든다.
단점:
- 함수를
main
함수 아래에 배치할 경우, 각 함수의 프로토타입(선언)을main
함수 이전에 추가해야 함. 이는 코드의 양을 약간 늘리고, 함수 선언과 정의 사이의 일관성을 유지해야 하는 추가적인 유지보수 작업을 발생시킴.
결론적으로, 어느 쪽이 더 나은가는 개발자의 선호도, 프로젝트의 규모 및 복잡성, 그리고 팀 내 코딩 관행에 따라 달라질 수 있다. 작은 프로젝트나 간단한 스크립트의 경우, 함수를 main
함수 위에 배치하는 것이 편리할 수 있고, 반면, 큰 프로젝트에서는 main
함수를 상단에 두고, 필요한 함수 프로토타입을 파일의 시작 부분에 명시한 후, 실제 함수 구현을 파일의 끝 부분에 위치시키는 것이 일반적인 관행이다.
교환
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h> // 표준 입출력 관련 함수를 사용하기 위해 stdio.h 헤더 파일을 포함합니다.
void swap(int *pa, int *pb);
/* swap 함수의 프로토타입 선언. 이를 통해 main 함수 이전에 swap 함수를 선언하여 컴파일러가
swap 함수의 존재를 인지하게 합니다. 이 함수는 두 개의 int 포인터를 매개변수로 받습니다. */
int main(void) // 메인 함수의 시작입니다. 프로그램의 실행이 여기서 시작됩니다.
{
int a = 10, b = 20; // 두 정수 변수 a와 b를 선언하고 각각 10과 20으로 초기화합니다.
swap(&a, &b); // swap 함수를 호출하여 a와 b의 주소를 인자로 전달합니다. 이를 통해 a와 b의 값을 교환합니다.
printf("a:%d , b:%d\n",a, b); // a와 b의 교환된 값을 출력합니다. swap 함수 호출 후 a의 값은 20, b의 값은 10이 됩니다.
return 0; // 메인 함수의 종료. 프로그램이 성공적으로 실행되었음을 나타내는 0을 반환합니다.
}
void swap(int *pa, int *pb) // swap 함수의 정의입니다. 이 함수는 두 개의 int 포인터를 매개변수로 받아 그 가리키는 값을 교환합니다.
{
int temp; // 임시 변수 temp를 선언합니다. 이 변수는 값 교환을 위해 필요합니다.
temp = *pa; // temp에 pa가 가리키는 변수의 값을 저장합니다. 이는 a의 현재 값을 temp에 저장하는 것과 동일합니다.
*pa = *pb; // pa가 가리키는 변수에 pb가 가리키는 변수의 값을 저장합니다. 즉, b의 값을 a에 저장합니다.
*pb = temp; // pb가 가리키는 변수에 temp의 값을 저장합니다. 이는 원래 a의 값을 b에 저장하는 것과 동일합니다. 이로써 a와 b의 값이 교환됩니다.
}
swap
함수가 변수의 값을 교환할 수 있는 이유는 매개변수로 변수의 주소를 받기 때문. 함수에 변수의 주소를 전달하면, 함수 내에서 이 주소를 통해 직접 해당 변수의 메모리에 접근하고 값을 변경할 수 있다. 이를 “포인터를 통한 간접 참조”. 이 방식을 사용하면 함수가 값을 반환하지 않아도 외부 변수의 값을 변경할 수 있다.
swap
함수의 동작 구체적 방식:
swap(&a, &b);
를 호출할 때,a
와b
의 메모리 주소가swap
함수의pa
와pb
매개변수에 각각 전달.- 함수 내에서,
pa
는pa
가 가리키는 주소, 즉a
의 주소에 저장된 값을 의미. 마찬가지로,pb
는pb
가 가리키는 주소, 즉b
의 주소에 저장된 값을 의미. - 함수에서 다음과 같이 값을 교환:
temp = *pa;
를 통해a
의 값을 임시 변수temp
에 저장.pa = *pb;
를 통해b
의 값을a
의 위치에 저장.pb = temp;
를 통해 임시 변수temp
에 저장된 원래a
의 값을b
의 위치에 저장.
이 과정을 통해 a
와 b
의 값을 교환할 수 있으며, 이 작업은 함수가 값을 반환하지 않아도 실행됨. 함수가 외부 변수의 주소를 매개변수로 받으면, 해당 함수는 이 주소를 통해 메모리에 직접 접근하여 변수의 값을 변경할 수 있음. 이렇게 포인터를 사용하는 기법은 C 언어에서 자주 사용되는 강력한 기능 중 하나.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h> // 표준 입출력 관련 함수를 사용하기 위해 stdio.h 헤더 파일을 포함합니다.
int temp;
int a = 10, b = 20;
void swap(int x, int y);
int main(void) // 메인 함수의 시작입니다. 프로그램의 실행이 여기서 시작됩니다.
{
swap(a, b);
printf("a:%d , b:%d\n",a, b);
return 0;
}
void swap(int x, int y)
{
temp = x;
a = y;
b = temp;
// printf("x:%d , y:%d\n",x, y);
}
위의 코드도 교환하는것처럼 보이지만 교환이라기보다 그냥 값을 재설정하는것에 불과함