2025.10.27 ~ 2025 10.31
이중 포인터 : 포인터를 가리키는 포인터
규칙
1. 포인터를 변수명으로 쓰면 그 안의 값이 된다.
- 이중 포인터에서는 이전 포인터의 주소 값_
2. 포인터에 &연산을 하면 변수의 주소가 된다.
- 자신의 주소 값 의미
3. 포인터에 *연산은 화살표를 따라간다.
- **ppi 는 ppi→ pi→ a
`void 포인터` : 사용을 위해서는 casting이 필요함~
`char 포인터` : 문자열을 출력시 `\0`문자 입력까지 값을 읽어오기에 배열 크기 정보가 없어도 괜찮.
주소와 포인터의 차이
배열의 사용
배열명은 기본적으로 포인터의 주소이므로 &연산자를 사용할 수 있다.
이 때 배열 전체를 하나의 변수로 생각하고 주소를 구할 수 있음.
char *ptr_arr[4];
🔴해당 변수 ptr_arr가 있을 때 ptr_arr와 &ptr_arr의 출력값은 같지만 +연산을 했을때에는 더해지는 값의 차이가 있다.
배열의 규칙
1. 배열은 전체가 하나의 논리적인 변수
2. 배열의 주소에 정수를 더하면 배열 전체의 크기를 곱해서 더한다.
이차원 배열과 이중 포인터의 차이 → 이중 포인터는 배열처럼 사용할 수 있지만 메모리 인덱싱 방식을 모른다 → 이때 배열의 크기 정보가 적어도 두개는 넘어가야한다.
⭐️2차원 배열의 요소를 참조하는 원리
ary[3][4] ⇒ ary+1 = *(ary+1) ⇒ ary[1]
*(ary+1)+2 ⇒ (ary+1) +(2 *sizeof(ary[1][0]))
*( *(ary+1)+2) ⇒ ary[1][2]
2차원 배열에서 다음 주소는 모두 같은 값을 가짐
하지만 자료형은 2,3/ 4,5 만 서로 같음
⇒ 배열은 주소뿐만 아니라 논리적으로 변수의 기능도 가능
동적 할당: 실행 시점에 메모리 공간을 할당하는 것.
배열처럼 사용하는 동적 할당의 예시
pi = (int *)malloc(5*sizeof(int)); // 저장공간 20바이트 할당

주의사항
1. HEAP은 프로그램 동작시 할당 영역이 지정되어 원하는 크기만큼 할당받지 못할 수도 있다.
2. 메모리 누수 방지를 위해 꼭 할당받은 메모리를 해제하는 작업이 필요하다
사용자가 만들어 쓰는 자료형으로 다양한 자료형을 묶은 복합 자료형으로 다양한 형태의 데이터를 처리할 수 있다.
☑️주요 Point
바이트 얼라이먼트 : 멤버 간의 크기가 다를 경우 패딩 바이트를 넣어 멤버를 가지런하게 정렬
-> 다음 변수의 크기를 확인하고 더 값이 크다면 패딩 추가
→ 이는 구조체 변수 선언의 순서에 따라 메모리 절약이 가능하다.
특징
⭐typedef 를 사용한 형 재정의
tydef struct student Student; //-> struct student 를 Student로 사용가능
//단축어 느낌
tydef unsigned int nbyte;
//한꺼번에 가능
typedef struct {
int num;
double grade;
}Student;
int main(void) {
Student s1 = { 321,3.6 };
}
구조체를 사용하는 흔한 방식 => 유용하게 쓰일 것 같아 기억에 꼭 넣어두자잉~🙋🏽
스트림 파일과 파일 포인터
장점
스트림 파일의 버퍼 공유와 fflush 함수
fgets 와 fscanf를 같이 쓸 때 생기는 문제
fscanf는 화이트 스페이스를 만나기 전까지 버퍼에 넣는다 → 이후 버퍼에 \n 은 남아있음 .
이후 fgets → \n 만 읽고 끝남.
그렇다면 fscanf로 문자열을 받아오면? 띄워쓰기를 입력으로 넣을 수 없음
🪨해결책 fflush → 스트림 파일의 버퍼를 비우는 함수 ⇒ \n 까지 버퍼를 지운다.
전처리 지시자
사용자 정의 헤더 파일을 사용하는 프로그램 #include “student.h” → 이렇게 “ “ 로 감싼다.
시스템 정의 공용 헤더파일은 <>로 표시하지만 " "로 감싸도 괜찮음
조건부 컴파일 지시자
#if #else #elif #ifdef #endif #ifndef
#ifdef ⇒ 해당 매크로가 정의되어 있으면 조건 충족
#ifndef ⇒ 매크로명이 정의되어 있지 않은 경우를 확인할 때
정의 여부만 확인할 수 있음
다른 조건식과 함께 사용할 때는 defined연산자 사용해야함
#if !defined BIT16 == #ifndef BIT16
#if → #endif 형식 : if의 조건문이 참이면 사이의 코드 컴파일
#error 조건을 만족하지 않아 컴파일 중단
#include<stdio.h>
#define VER 6
#if VER >=6
int main(void) {
printf("정상 실행");
#else
#error 버전은 6.0 이상이어야합니다.
#endif
FILE* fp;
int arr[10] = { 13,10,13,13,10,26,13,10,13,10 };
int i, res;
}
//ver을 5로 바꾸니까 아예 빌드가 되지가 않는다.
상당히 중요한 내용이다. 함수를 분리해 코딩을 하면서 중복 문제를 여럿 겪은 적이 있다.
헤더파일을 재활용하는 경우 중복 선언이 될 수 있고 이는 변수의 값 변경으로 이어질 수 있다.
따라서 extern 과 static을 적절히 사용해 파일의 변수 공유를 막아야한다.
extern : 다른 파일에서 선언된 전역 변수를 사용할 때 extern 사용
| static : 다른 파일에서 전역 변수를 공유하지 못하게 할 때 사용
정적 전역 변수는 하나의 파일 내에서만 사용된다 → 이로 인해 다른 파일과의 공유는 차단됨.
다른 파일에서 같은 이름의 전역 변수를 선언해 새로 사용할 수 있음
⚠️일반 전역 변수는 동일한 이름의 전역 변수 선언 시 컴파일 에러 발생
함수에도 static 사용 가능하다 ⇒ 소스 파일 내부에서만 사용되는 함수 정의 예약어
⇒ 동일하게 다른 파일에서 동일한 이름의 함수 선언 가능
static이 없는 함수는 기본적으로 extern 선언으로 간주
중복 문제 → 헤더 파일을 재활용 하는 경우 중복 선언이 될 수 있기에 문제 해결 필요
#ifdef _POINT_H_ #define _POINT_H_ //같은 헤더 파일이 두번 이상 포함될때 헤더 파일이 중복 포함되지 않도록 함 typedef struct { int x; int y; }Point; #endif // 중복 정의 방지 code ---------------------------- #pragma once //⭐다른 전처리 -> 한번만 컴파일 해라.! // 더 최신 버전의 컴파일에서 해당.함수의 선언이나 extern 선언의 경우 중복 선언이 가능하지만 구조체는 중복 선언이 허용되지 않음.
→ 이때 헤더 파일을 찾아 중복 선언이 되지 않도록 하는 것도 가능하지만 일일이 포함 관계를 고려하기는 힘들다. ⭐
이렇게 1주하고도 절반만에 c언어 학습이 끝났다. 기존에 알고 있는 내용도 있었지만 새로 알게 된 방법 또한 있었고 재밌는 학습과정이었습니다~
앞으로는 C++ 학습으로 넘어가게 될 텐데 이는 C와 C++의 차이와 객체 지향 프로그래밍의 특징 위주로 정리해보도록 하겠습니다.