ex.250512 공부노트 - Hwanghyewon06/c- GitHub Wiki

🔹 전체 코드

#include <stdio.h>

int main()
{
    int n = 10;
    int n2 = n;
    int* p = &n;
    int* p2 = p;
}

✅ 한 줄씩 분석

int n = 10;

  • **정수형 변수 n**을 선언하고 값 10을 저장합니다.
  • 이 변수는 스택 메모리(stack)에 저장됩니다.
  • 예) n의 주소가 0x100이라면, n에는 10이라는 값이 저장됨.
n (주소: 0x100) → 10

int n2 = n;

  • n의 값을 복사하여 **새로운 변수 n2**에 저장합니다.
  • n2도 스택에 저장되며, n과는 완전히 독립된 메모리 공간을 가집니다.
  • 즉, n2를 바꿔도 n은 영향을 받지 않습니다.
n2 (주소: 0x104) → 10

int* p = &n;

  • pint형을 가리키는 포인터 변수입니다.
  • &nn의 주소값 (예: 0x100)이므로, p에는 n의 주소가 저장됩니다.
  • *p를 사용하면 n의 값(10)에 접근할 수 있습니다.
p (주소: 0x108) → 0x100 (n의 주소)
*p → 10

int* p2 = p;

  • p2int형 포인터입니다.
  • p가 가리키는 주소(즉, n의 주소)를 그대로 복사해 저장합니다.
  • 따라서 p2n을 가리키며, *p2 == 10 입니다.
p2 (주소: 0x10C) → 0x100 (n의 주소)
*p2 → 10

✅ 시각화된 메모리 구조 (예시)

[ 변수명 ]   [ 메모리 주소 ]   [ 저장값 ]          [ 의미 ]
-------------------------------------------------------------
n           0x100             10                 정수 값
n2          0x104             10                 n의 값 복사
p           0x108             0x100              n의 주소
p2          0x10C             0x100              p의 값 복사 (역시 n의 주소)

✅ 요약 정리

항목 설명
n 정수 변수, 값 10 저장
n2 = n n의 값을 복사한 독립 변수
p = &n 포인터 p가 변수 n의 주소를 가짐
p2 = p 포인터 p2p와 같은 주소(n의 주소)를 가짐
*p, *p2 모두 n의 값을 간접적으로 참조 (10)

✅ 1. char와 문자열 처리, 아스키 코드

🔹 예제 코드

char* s = "ABC";
 
printf("%c %d\n", s[0], s[0]); // A 65 

🔸 개념 설명

char는 1바이트(8비트)의 정수형 타입으로, 문자를 저장합니다.

C 언어에서 문자열은 char 배열로 표현되며, 마지막에는 항상 '\0' (NULL 문자)로 끝남.

"ABC"는 다음과 같이 저장됨:

+----+----+----+----+
 | A | B | C | \0 | 
+----+----+----+----+ 
주소: s s+1 s+2 s+3 

s[0] == 'A', 'A'의 아스키 코드값은 65입니다.

✅ 2. 포인터의 기본 개념과 문자열 포인터 🔹 예제 코드

char* s = "ABC"; 

printf("%s\n", s); // ABC 

printf("%s\n", s + 1); // BC 

🔸 개념 설명

char* s는 문자열 상수 "ABC"의 시작 주소를 가리키는 포인터입니다.

s + 1 → 포인터 연산으로 한 문자(1바이트) 뒤를 가리킵니다. 즉, "ABC"의 두 번째 문자 'B'부터 출력 → "BC"

✅ 3. 문자열을 아스키 값으로 출력 🔹 예제 코드

void PrintStringToAscii(char* s1) 

{ 

for (int i = 0; s1[i] != '\0'; ++i)

 printf("%c : %d\n", s1[i], s1[i]); 

} 

🔸 개념 설명

각 문자를 반복문으로 접근하여 출력

%c는 문자, %d는 해당 문자의 아스키 코드 (정수값)

예: "ABC" →

A : 65 B : 66 C : 67

✅ 4. double 자료형과 포인터 연산 🔹 예제 코드

double da[4] = { 1.1, 2.2, 3.3, 4.4 }; 

double* pd = &da[1]; 

printf("%g %g\n", da[1], pd[0]); 
// 2.2 2.2 

printf("%g %g\n", da[2], pd[1]); 
// 3.3 3.3 

🔸 개념 설명

double은 실수형 타입 (8바이트)

double* pd = &da[1]는 da[1] 즉 2.2의 주소를 가리킴

pd[1] == *(pd + 1) == da[2] == 3.3

포인터 연산에서 pd + 1은 8바이트 뒤 주소로 이동

✅ 5. 배열과 포인터 차이 🔹 예제 코드 char* s = "ABC"; char arr[4] = "ABC"; 🔸 개념 설명

특성 포인터 (s) 배열 (arr)

메모리 할당 코드 영역

(읽기 전용) 스택 메모리 수정 가능성 X

(컴파일러 경고/에러 발생 가능) O (가능)

크기 포인터 자체는 8바이트 (x64 기준)

데이터 크기 만큼 (여기선 4바이트)

"ABC"는 컴파일 시 메모리에 상수로 저장됨

포인터는 문자열의 첫 글자 주소만 저장함

배열은 실제 문자열을 스택에 복사함

✅ 6. 포인터 연산 및 주소 출력 🔹 예제 코드

int n = 10;
 
int* p = &n; 

printf("%p %p\n", &n, p); 

printf("%p %p\n", &n + 1, p + 1); 

🔸 개념 설명

%p는 주소 출력

p + 1은 sizeof(int)(보통 4바이트) 만큼 주소 증가

p + 1은 실제 메모리 상에서 4바이트 다음 위치를 가리킴

✅ 7. 포인터 다양성 — char*, int*, double*

포인터 타입

단위 연산 크기 (p + 1) 설명

char* 1바이트 문자열,

문자 배열 처리

int* 4바이트 (보통) 정수 배열 처리

double* 8바이트 실수 배열 처리

배열 이름은 주소

arr[0]의 주소는 &arr[0]

arr == &arr[0]

포인터와 배열의 공통점

arr[i] == *(arr + i)

p[i] == *(p + i) (포인터도 인덱스로 사용 가능)

✅ 8. 문자와 정수의 연관성 (아스키 코드) 🔹 예제 코드 int n1 = 65;

int n2 = 'A';

printf("%d %d\n", n1, n2); // 65 65

printf("%c %c\n", n1, n2); // A A

🔸 개념 설명

문자 'A'는 내부적으로 정수 65로 저장됨

%d → 정수로 출력

%c → 문자로 출력

따라서 int와 char는 변환이 가능 (단, 범위에 주의)

✅ 9. 요약 — 개념별 핵심 정리 개념 설명 char 1바이트 문자 자료형, 문자열 구성 double 8바이트 실수 자료형 포인터

변수(또는 배열)의 주소 저장 배열 이름 배열의 첫 요소 주소 (arr == &arr[0])

아스키 코드 문자를 정수로 표현하는 시스템 ('A' == 65)

포인터 연산 p + 1은 타입 크기만큼 이동

(int*은 4바이트 증가) 문자열 char 배열 + 마지막에 \0 포함

%c %d %p %s 각각 문자, 정수, 주소, 문자열 출력 포맷

좋습니다! 아래는 코드에 등장하는 각 자료형, 포인터, 메모리 구조를 중심으로 기초부터 정확하게 설명한 내용입니다. 배열과 포인터가 메모리에서 어떻게 동작하는지를 시각적으로 이해할 수 있게 정리했습니다.


✅ 전체 코드

#include <stdio.h>

int main()
{
    char arr[3] = { 10, 20 ,30 };
    double darr[4] = { 10.1, 20.2, 30.3, 40.4 };
    char* pc = &arr[0];
    double* pd = &darr[0];
}

✅ 한 줄씩 설명

🔹 char arr[3] = {10, 20, 30};

  • char 타입은 1바이트 크기의 정수형 자료형입니다.
  • arr크기 3인 문자형 배열이며, 메모리에 연속적으로 저장됩니다.
  • 배열 초기값: arr[0] = 10, arr[1] = 20, arr[2] = 30

예를 들어 메모리 구조는 이렇게 될 수 있습니다 (주소는 예시):

주소    값
0x100   10   ← arr[0]
0x101   20   ← arr[1]
0x102   30   ← arr[2]

🔹 double darr[4] = {10.1, 20.2, 30.3, 40.4};

  • double 타입은 8바이트 크기의 실수형 자료형입니다.
  • darr4개의 실수형 데이터를 저장하는 배열이며, 각 요소는 8바이트씩 차지합니다.

예시 메모리 구조:

주소      값
0x200     10.1   ← darr[0]
0x208     20.2   ← darr[1]
0x210     30.3   ← darr[2]
0x218     40.4   ← darr[3]

참고: double 배열의 각 요소는 8바이트 간격으로 메모리에 저장됨


🔹 char* pc = &arr[0];

  • pcchar 타입을 가리키는 포인터 변수
  • &arr[0]는 배열 arr의 첫 번째 요소의 주소 (예: 0x100)
  • 따라서 pcarr 배열의 시작 주소를 가리킵니다
pc → 0x100 (arr[0]의 주소)
*pc == 10

🔹 double* pd = &darr[0];

  • pddouble 타입을 가리키는 포인터
  • &darr[0]는 배열 darr의 첫 번째 요소의 주소 (예: 0x200)
  • pddarr 배열의 시작 주소를 가리킴
pd → 0x200 (darr[0]의 주소)
*pd == 10.1

✅ 시각화된 메모리 구조 (예시)

[ 배열 arr (char[3]) ]          [ 배열 darr (double[4]) ]
주소      값                    주소         값
0x100     10   ← arr[0]         0x200        10.1   ← darr[0]
0x101     20   ← arr[1]         0x208        20.2   ← darr[1]
0x102     30   ← arr[2]         0x210        30.3   ← darr[2]
                                0x218        40.4   ← darr[3]

[ 포인터 ]
pc = 0x100 → arr[0]
pd = 0x200 → darr[0]

✅ 요약 표

항목 설명
char arr[3] 3개의 1바이트 정수 배열, 연속된 메모리에 저장
double darr[4] 4개의 8바이트 실수 배열, 각 요소는 8바이트 간격으로 저장
char* pc arr[0]의 주소를 가리킴 (pc = &arr[0])
double* pd darr[0]의 주소를 가리킴 (pd = &darr[0])
포인터 연산 pc + 1 → 1바이트 증가, pd + 1 → 8바이트 증가

✅ 추가 개념: 포인터 연산

표현 의미
pc + 1 1바이트 다음 주소 (0x101)
pd + 1 8바이트 다음 주소 (0x208)
*pc arr[0]의 값 (10)
*pd darr[0]의 값 (10.1)
⚠️ **GitHub.com Fallback** ⚠️