공부/C++

문자열, 문자열 특성, 문자 배열과 문자열 차이, 문자열 입력받기, 문자열 관련 함수, 포인터, 포인터 사용, 주소 연산자 &, 간접 참조 연산자 *, 더블 포인터, 주소 연산

월러비 2025. 6. 5. 18:05

cmd

  • 폴더 경로 변경 : cd 폴더 경로
  • 폴더 내부 파일 정보 확인 : dir
  • 폴더 내부 파일 실행 : 파일 이름.exe

문자열

  • 변수와 상수의 차이 : 상수는 읽기만 가능하고 쓰기가 되지 않는다.
  • 리터럴 : 그자체로 값의 역할을 하는 메모리공간이다.
    • ‘문자1개’ : char 형, 해당 문자의 아스키코드(정수)가 저장되게 된다.
    • “문자열” : char 형, [ ] 배열로 받는다. / 이 경우는 배열의 마지막에 ‘NULL’ 문자가 들어간다.
      • 문자열 %s로 출력이 가능하게 된다.
  • printf는 NULL문자를 만나면 ‘종료’하기 때문에 [1024] 크기의 배열이라도 모든 공백이 출력되지는 않는다.

문자열 특성

  • C언어에서 문자열은 문자 배열로 표현
  • 문자열의 끝은 null 문자('\0')로 표시
  • 문자열 리터럴은 자동으로 null 문자 추가

문자 배열과 문자열 차이

char s[5] = { 'h', 'e', 'l', 'l', 'o' };
printf("%s\\\\n", s);
  • null 문자가 없는 문자 배열
    • \0 또는 NULL을 작성해야한다.
    • 문자 배열은 NULL문자가 없다.
    • NULL을 만나야 끝나는것이기에 배열 길이 이상을 탐색하다 NULL을 만나서 종료된것이다.
      • 배열의 길이(메모리)를 초과했다.
  • %s로 출력 시 예상치 못한 결과 발생 가능
    • 발생 이유 : 배열의 이름(s)를 적었다.
    • 배열의 이름은 ‘배열의 주소’(배열 첫 요소의 주소)다.
    • 즉, 주소만 넘겼지 배열의 길이는 모른다.
  • 문자열로 사용하려면 null 문자 추가 필요

문자열 입력받기

  • scanf와 %s 형식 지정자 사용
    • &(주소 연산자)를 쓰지 않고 변수 이름만 쓴다.
    • 이유 : 배열의 이름 자체가 주소를 가리키기 때문이다.
  • 공백 문자까지 입력받으려면 fgets 함수 활용

문자열 관련 함수

  • strlen: 문자열 길이 반환
    • strlen(배열이름)
    • 처음부터 NULL문자가 나올때까지 문자갯수를 카운팅한다.
  • strcpy: 문자열 복사
    • strcpy(배열 이름1, 배열 이름2)
    • 배열 이름1에 배열 이름2의 내용물을 복사한다.
      • 마지막 부분인 NULL문자까지 복사한다.
    • 메모리 크기를 맞춰야한다.
    • 배열 이름2 대신 “문자열”을 넣어도 가능하다.
  • strcat: 문자열 연결
    • strcat(배열 이름1, 배열 이름2)
    • 배열 이름2의 내용물을 배열 이름1의 내용물 뒤에 붙인다.
  • strcmp: 문자열 비교
    • strcmp(배열, 배열)
    • <0 : 문자가 사전순으로 낮을때
    • == 0 : 문자가 일치할때
    • 0 : 문자가 사전순으로 빠를때

포인터

  • 포인터 : 포인터 데이터형, 포인터 변수, 포인터(메모리 주소) 3가지를 모두 말하는 단어다.
  • 주소값의 사이즈는 ‘고정’되어있다.
  • 사용 이유
    • 배열을 통째로 넘기는 함수는 없다.
      • 배열의 초기 주소를 넘겨서 배열을 넘길 수 있다.
    • 동적할당 시에 메모리 주소만 알려준다.
      • 알려주는 메모리 주소를 통해 동적할당된 값을 사용한다.
  • 변수가 반환하는 값은 *을 하나 빼면 뭐가 남는지 보는것이다.
    • int**를 변수로 출력하면 → int* 변수값이 리턴된다.
    • int*를 *변수로 출력하면 → int 변수값이 리턴된다.

포인터 사용

int a = 10;
printf("%d\\\\n", &a);
  • 주소 연산자(&) : 피연산자 한개를 취하는 연산자다.
    • &a: 변수 a의 메모리 주소를 반환
      • 반환하는 값은 int* 형(메모리 주소)이다.
    • 주소값은 실행할 때마다 다를 수 있음
      • 사용하지 않는 메모리 공간에서 데이터 형의 메모리 크기만큼 사용하는 것이다.
    • %p: 메모리 주소를 출력하는 서식지정자다.
  • 16진수 : 4바이트
  • 64비트 → 8바이트 → 8비트 = 1바이트
int a = 10;
int* ptr_a;
ptr_a = &a;
//int* ptr_a = &a; //선언 및 초기화도 가능하다.

*ptr_a = 20;
printf("a = %d\\\\n", a);
printf("*ptr_a = %d\\\\n", *ptr_a);

--결과--
a = 20
*ptr_a = 20
  • 자료형* : 포인터 형 변수
    • 메모리 주소를 저장하는 변수다.
    • 값은 메모리 주소를 리턴한다.
    • 자료형 : 메모리주소의 데이터형
    • 즉, 메모리 주소가 가리키는 곳으로 가면 자료형의 값이 있다는 것이다.
    • 포인터 변수 자체는 ‘메모리 주소’의 저장이기에 직접 값을 넣을 수는 없다.
      • 포인터 연산자가 필요하다.
  • 간접 참조 연산자 (*) : ‘포인터 연산자’ 라고도 부른다.
    • 포인터 변수에 사용한다.
    • 포인터 변수에 저장된 메모리 주소에 담겨진 데이터를 읽고 쓸 수 있다.
      • 읽고 쓰는 데이터는 선언한 자료형의 데이터형이다.
      • int* → int 형 값을 읽고 쓴다.
    • 포인터 연산자를 써서 값을 넣으면, 해당 포인터 변수에 저장된 메모리 주소에 저장된 값이 변경된다.
    • 즉, 포인터 변수에 담겨진 메모리 주소에 접근하게 되는 것이다.
  • 역참조 : 포인터가 기리키는 변수에 접근하는 작업을 의미한다.
  • int* ptr_a: 정수를 가리키는 포인터 변수 선언
  • ptr_a = &a: 포인터에 변수 a의 주소 저장
  • ptr_a = 20: 포인터가 가리키는 위치의 값을 20으로 변경

더블 포인터

  • 포인터 변수처럼 메모리 주소 변수를 가리키는 메모리 주소 변수다.

주소 연산

int a = 10;

printf("&a = %d\\\\n", &a);
printf("(&a) + 1 = %d\\\\n", (&a) + 1); //주소값 + 4
printf("(&a) + 2 = %d\\\\n", (&a) + 2); //주소값 + 8

int a = 10;
int* ptr_a = &a;

printf("ptr_a = %d\\\\n", ptr_a);
printf("ptr_a + 1 = %d\\\\n", ptr_a + 1);
printf("ptr_a + 2 = %d\\\\n", ptr_a + 2);
  • 산술 연산자 (+)는 좌항과 우항의 자료형이 다르면 결과값이 다르게 작동한다.
    • 포인터 값 + 상수 : 포인터변수의 자료형의 크기만큼 올라간다.
  • 주소에 1을 더하면 다음 변수 크기만큼 주소 증가
  • int형의 경우 4바이트씩 증가
  • 포인터 연산은 해당 데이터 타입의 크기 단위로 수행
  • 배열과 함께 사용할 때 유용