포인터 레퍼런스 리터럴

niraaah·2023년 4월 4일
2

혼자하는 스터디

목록 보기
2/25
post-thumbnail

[ in C ]

포인터: 메모리 상에 위치한 특정 데이터의 (시작) 주소값을 보관하는 변수

(포인터에 저장되는 주소값의 데이터형)* (포인터의 이름)

ex)

int *pa;

&(주소값을 저장할 데이터) = 주소값

ex)

&a = pa;

const = 이 데이터의 값은 절대로 바뀌면 안된다

ex)

const int* pa = &a

: const int 형 변수를 가리킨다는 것이 아님. int형 변수를 가리키는데 pa가 가리키는 값을 절대 바꾸지 말라는 뜻. 즉 이 문장에서 pa는 반드시 a의 주솟값만 가리키도록 하고 a에 담기는 값은 변할 수 있음을 의미한다. 그래서 이 문장 이후에 'pa = &b'같은 문장은 에러가 난다.

&와 *은 상쇄된다는 늒김으로다가....

포인터는 자신이 가리키는 데이터의 '형'의 크기를 곱한 만큼 덧셈을 수행한다.

ex) pa라는 포인터가 int a를 가리킨다면, p + 1을 하면 p의 주솟값에 1x4(= 4)가 더해지는 것이고, p + 3을 하면 p의 주솟값에 3x4(= 12)가 더해지는 것이다.

배열에서 배열의 이름은 배열의 첫번째 원소의 주솟값을 가리키는 포인터가 된다.

: 배열의 이름과 배열의 첫번째 주소값은 엄밀히 다른 것이지만, 배열의 이름을 사용했을 때 암묵적으로 첫번째 원소를 가리키는 포인터로 타입 변환이 되기 때문이다!
ex)

arr[10] = {1, 2, 3, ..., 10};

에서 'arr'의 값 = '&arr[0]'의 값


[ in C++ ]

레퍼런스(참조자)

ex)

int& another_a = a;

= another_a는 a의 참조자다. 즉, another_a는 a의 또다른 이름이라고 컴파일러에게 알려주는 것. ("another_a야, 너는 이제부터 a의 또다른 이름이야.") 따라서, another_a에 수행하는 작업은 사실상 a에 수행하는 작업.

포인터와 비교되는 레퍼런스의 특징
1. 레퍼런스는 반드시 처음에 누구의 별명이 될 것인지 지정해야함. (int* pa;는 가능하지만 int& another_a;는 불가능)
2. 레퍼런스가 한 번 누군가의 별명이 되면 다른 이의 별명이 될 수 없다.
3. 포인터와 달리 레퍼런스는 메모리상에 존재하지 않을수도 있다.
4. 불필요한 &와 *가 없어서 코드가 훨씬 간결해짐.
(C++ 문법상 참조자의 참조자를 만드는 것은 금지되어 있음)

+) scanf 쓸때는 &another_a 해줘야하는데 cin 쓸때는 & 없이 그냥 another_a 해도 됨!

{리터럴(literal): 소스 코드 상에서 고정된 값을 가지는 것. 리터럴이 보관되는 곳은 오직 읽기만 가능한 곳.}
{참고적으로 VS 2017 이상에서는 리터럴을 char* 가 가리킬 수 없습니다. 반드시 const char* 가 가리켜야 하며, 덕분에 리터럴을 수정하는 괴랄한 짓을 컴파일 단에서 막을 수 있습니다.}

+) 함수를 만들 때 반드시 고려해야 할 사항
1. 이 함수는 무슨 작업을 하는가? (자세하게)
2. 함수의 리턴형이 무엇이면 좋을까?
3. 함수의 인자으로는 무엇을 받아야 하는가?

ex) 문자열 복사하기

#include <stdio.h>
int copy_str(char *src, char *dest);
int main() {
 char str1[] = "hello";
 char str2[] = "hi";

 printf("복사 이전 : %s \n", str1);

 copy_str(str1, str2);

 printf("복사 이후 : %s \n ", str1);

 return 0;
}
int copy_str(char *dest, char *src) {
 while (*src) {		//*src = NULL(= 0)이 될 때까지
   *dest = *src;	//src의 문자를 dest에 대입
   src++;			//배열의 다음 원소를 가리키게 함
   dest++;			//배열의 다음 원소를 가리키게 함
 }

 *dest = '\0';
 
/*
위의 while문에서 src가 NULL 이 된다면
while문을 종료해 버렸기 때문에 src 에 넣을 틈이 없었는데
마지막에 위와 같이 처리해줌으로써
dest 에 NULL 문자를 끝부분에 삽입할 수 있게 됨
*/

 return 1;
}

ex) 문자열 더하기

/*
dest에 src 문자열을 끝에 붙인다.
이 때 dest 문자열의 크기를 검사하지 않으므로
src가 들어갈 수 있는 충분한 크기가
있어야 한다.
*/

int stradd(char *dest, char *src) {
  //dest 의 끝 부분을 찾는다.
  while (*dest) {
    dest++;
  }

/*
while문을 지나고 나면 dest는
dest 문자열의 NULL 문자를 가리키고 있게 된다.
이제 src의 문자열들을 dest의 NULL 문자 있는 곳 부터
복사해넣는다.
*/

  while (*src) {
    *dest = *src;
    src++;
    dest++;
  }

/*
마지막으로 dest 에 NULL 추가 (왜냐하면 src 에서 
NULL 이 추가 되지 않았으므로) 
 */
 
  *dest = '\0';

  return 1;
}

ex) 문자열 비교하기

int compare(char *str1, char *str2) {
  while (*str1) {
    if (*str1 != *str2) {
      return 0;
    }

    str1++;
    str2++;
  }

  if (*str2 == '\0') return 1;

  return 0;
}

+ 2차원 배열 동적 할당

(in C++)

[코드]
#include <cstdio>
#include <cstdlib>

//int형 2차원 배열 동적 할당 함수
int** alloc2DInt (int rows, int cols){
	if( rows <= 0 || cols <= 0 ){
    	return NULL;
    }
    int** mat = new int* [rows];
    for (int i = 0 ; i < row ; i++){
    	mat[i] = new int [cols];
    }
    return mat;
}

//int형 2차원 배열 동적 해제 함수
void free2DInt (int** mat, int rows, int cols = 0){
	if ( mat != NULL){
    	for (int i = 0; i < row; i++)
        	delete [] mat[i];
        delete [] mat;
    }
}

//동적 생선된 2차원 배열을 랜덤으로 초기화하는 함수
void set2DRandom (int** mat, int rows, int cols){
	for (int i = 0; i < rows; i++){
    	for (int j = 0; j < cols; j++){
        	mat[i][j] = rand()%100;
        }
    }
}

//2차원 배열을 화면으로 보기 좋게 출력하는 함수
void print2DInt (int** mat, int rows, int cols){
	printf("행의 수 = %d, 열의 수 = %d", rows, cols);
    for (int i = 0; i < rows; i++){
    	for (int j = 0; j < cols; j++){
        	printf("%4d", mat[i][j]);
        }
    }
}

//주 함수: 2차원 배열 동적 할당 테스트
void main(){
	int** mat;
    int rows, cols;
    
    printf("행과 열의 크기를 입력하시오: ");
    scanf("%d%d", &rows, &cols);
    
    mat = alloc2DInt( rows, cols );
    set2DRandom( mat, rows, cols );
    print2DInt( mat, rows, cols );
    free2DInt( mat, rows, cols );
}

[실행 결과]
행과 열의 크기를 입력하시오: 4 6
행의 수 = 4, 열의 수 = 6
41	67	34	0	69	24
78	58	62	64	5	45
81	27	61	91	95	42
27	36	91	4	2	53
계속하려면 아무 키나 누르십시오...
profile
코딩천재

2개의 댓글

comment-user-thumbnail
2023년 4월 4일

잘보고 갑니다

답글 달기
comment-user-thumbnail
2023년 4월 6일

다음 글은 언제 올라오나요?

답글 달기