Programming Language
[C] 다차원 배열
[C] 다차원 배열
2022.05.01먼저 배열의 종류에 대해 알아보자. static배열과 Fixed Dynamic배열은 컴파일 할 때 배열의 최대 범위가 정해지지만, Dynamic배열은 배열의 최대 범위가 계속해서 변할 수 있다. (Java의 ArrayList와 비슷한데, 일단은 ArrayList도 배열이라고 개념적으로 생각하자.) 배열을 관리할 때는 Descriptor를 사용한다. Descriptor는 배열을 선언한 뒤 선언된 배열을 저장할 때 사용된다고 이해하면 되고, 컴파일 시에 사용된다. 즉, 메모리를 할당하는 코드를 생성하기 위해 Descriptor가 사용되고, 왼쪽 그림과 같은 정보를 지닌다. 컴파일 말고 런타임 과정에서도 Descriptor를 가질 수 있는데, Java를 생각하면 이해하기 쉽다. Java에서 배열을 다룰 때 i..
[C] 정리 (1)
[C] 정리 (1)
2022.04.18sizeof연산자는 byte단위의 정수로 타입의 크기를 반환하며, 반환 타입은 size_t이다. (unsinged int 와 비슷) sizeof('A)의 결과는 1이 아니라 4이다. 컴파일 시 문자코드로 바뀌고, int타입으로 인식된다. 증감 연산자의 전위형(prefix) j = ++i; // 값이 참조되기 전에 증감연산자가 실행된다. 증감 연산자의 후위형(prefix) j = i++; // 값이 참조된 후에 증감연산자가 실행된다. 독립적인 하나의 문장으로 쓰일 경우에는 아무 차이가 없다. 큰 타입으로 자동으로 형변환 되지만, 비트 수가 맞지 않으면 값의 손실이 발생할 수 있다. null문자의 문자 코드는 0이다. 실수형은 근사값으로 저장되기에, 값을 비교할 때 오차가 발생할 수 있다. double타입과..
[C] const
[C] const
2022.04.13자바에서는 변수를 상수로 사용할 때 사용하는 키워드인 const이다. C는 시스템과 관계가 깊은 언어이기에 const키워드가 매우 중요하고, 나아가 C++까지도 영향을 미치는 키워드이다. const int * ptr 포인터 변수 앞에 const를 붙이는 경우를 살펴보자. "ptr주소를 통해 찾아간 값은 변경할 수 없다" 라는 의미를 지닌다. int num = 5; const int * ptr = # *ptr = 10; // ptr을 통해서는 값을 변경할 수 없다. 오류. num = 20; // 이거는 상관없음. ptr을 통해 변경하는거만 금지 const int num = 5; int * ptr = # // num은 상수인데, ptr을 통해 값이 변경될 수 있어서 오류! const int *..
[C] Call By Value
[C] Call By Value
2022.04.13#include #include int main() { int a = 10; int b = 20; int c = add(a,b); } int add(int n1, int n2){ int n3; n3 = n1 + n2; return n3; } 위의 코드처럼 함수를 호출하면, a와b에 대한 값은 변화 없이 지역변수에 복사만 하고 로직을 수행한다. 이를 Call By Value라고 한다. CBV를 사용해 코드를 작성하면, 값들을 재사용하기 좋고, 디버깅 할 때도 집중해서 관찰해야 하는 값이 한정되기 때문에 편하다. Java로 함수를 작성할 때도 CBV형식으로 작성하는 경우가 많았을 것이다. 함수에서 값 대신 포인터를 입력받도록 하면, main함수의 변수에 대해서도 값을 바꿀 수 있다. C에서 입력은 scanf..
[C] 포인터와 함수
[C] 포인터와 함수
2022.04.13배열을 할당받은 변수명은 포인터 타입이다. 함수를 통해 배열을 전달하면, 배열 자체가 전달될까 아니면 포인터가 전달될까? 함수의 인자로 배열을 입력하면 주소 즉, 포인터가 복사돼 전달된다. 지난번에 스택프레임에 대해 배울 때 메모리 스택에서 활성화 된 값들만 조작할 수 있다고 배웠는데, 포인터를 사용하면 비활성화된 스택 프레임에도 접근할 수 있다. 그런데, 배열을 포인터로만 전달하게 되면 배열의 길이에 대한 정보는 전달하지 못한다. 배열에 있는 요소들의 합을 구하는 함수를 작성하고 싶은데, 이런 경우는 어떻게 해야 할까? 함수로 배열을 넘겨줄 때 배열의 길이를 함께 지정해 줄 수 있다. 일단 배열을 받는 함수는 정수 포인터 타입의 변수로 받아오고, 배열의 길이에 대한 정보인 len을 추가로 받는다. 물론..
[C] 문자열과 포인터
[C] 문자열과 포인터
2022.04.01지난번에 배웠듯 C에서 문자열을 표현할 때는 char타입의 배열을 사용해 마지막에 null (\0)문자를 붙이는 것으로 표현할 수 있다. 그런데 포인터 변수로도 배열을 표현할 수 있다면, 문자열도 포인터 변수로 표현할 수 있지 않을까? 표현할 수 있다. 하지만 첫 번째 방법과 두 번째 방법은 차이점이 있다. char * s1 = "your team"; 처럼 포인터 변수를 사용해 문자열을 표현하면, 문자열을 새로 할당하는 것도 가능하고, 문자열이 아니라 char의 주소를 할당하는 것도 가능하지만, 문자열의 일부분을 인덱스를 통해 변경하려고 하면 오류가 발생한다. 이는 자동 할당된 문자열에 대한 규칙으로 받아들여야 한다. char타입의 배열로 문자열을 선언하게 되면 아까와는 반대되는 상황이 발생한다. 배열 ..
[C] 포인터 연산
[C] 포인터 연산
2022.04.01포인터도 값이니 사칙연산이나 증감 연산자를 적용할 수 있지 않을까? #include #include int main() { int num = 1234; int *p = # printf("%p\n", p); printf("%p", p+1); } 포인터p의 값이 1000이라고 했을 때 p+1은 1001이 될까? 포인터 변수에 대해서도 덧셈과 뺄셈은 수행할 수 있지만, 정수 변수의 덧셈과는 다른 양상을 보인다. 변수의 타입에 따라 연산의 단위가 달라진다. 주소를 값으로 바꿔주는 * 연산자에 대해서 덧셈과 뺄셈을 수행해도 직관적인 결과를 얻을 수 있다. 배열과 같은 양상으로 연산을 수행한다. 당연하겠지만, *(ptr) +1을 출력하면 12가 출력되고, 배열 범위를 벗어나면 오류 대신 쓰레기값이 출력된다...
[C] 배열과 포인터
[C] 배열과 포인터
2022.04.01자바에서의 배열과 C에서의 배열은 성격이 좀 다르다. 일단, 배열을 선언한 변수 이름은 배열의 시작 주소를 의미하는 포인터이다. ( arr = &arr[0] ) 자바에서는 arr을 객체로 저장해 arr자체로는 뭐 할 수 있는게 많이 없지만, C에서는 그 자체로도 의미하는 바가 있다. 그러면, 변수명이 배열의 시작 주소를 의미한다고 했으니.. 특정 주소를 할당할 수도 있지 않을까? 라고 생각할 수도 있지만, 할당은 불가능하다. 포인터변수와 배열의 변수명은 굉장히 유사하지만, 배열의 변수명에다가 값을 새롭게 할당할 수는 없다. (읽기는 가능) int main() { int arr[3] = {0, 1, 2}; arr[0]++; printf("%d \n", *arr); // 1 printf("%d \n", ar..
[C] 포인터
[C] 포인터
2022.03.28포인터는 메모리 공간의 주소를 의미한다. 포인터만 따로 처리하는 타입으로 포인터 타입이 있다. ( * 로 표시하고, "%p"를 사용 ) 변수를 저장할 때 처음부터 포인터와 값을 함께 기록하면 좋지만, 저장할 때 메모리 공간이 따로 들어가고 매번 값을 확인해야 하기 때문에 잘 사용하지 않는다. 대신 크기별로 전담 변수를 둬 데이터의 타입으로 덩어리의 크기를 표현하는 방법을 사용한다. (int타입이면 int포인터, char타입이면 char포인터) int형 포인터 ptr1에 대해서 주소로 접근해 데이터를 읽을 때는 4byte를 한 덩어리로 보고 읽어온 값은 int형으로 처리한다. char형 포인터 ptr2에 대해서 주소로 접근해 데이터를 읽을 때는 1byte를 한 덩어리로 보고 읽어온 값은 char형으로 처리..
[C] 문자열
[C] 문자열
2022.03.28C에서는 boolean타입도 없지만 String타입도 없다. boolean대신 int타입을 대신해서 사용했고, String타입 대신 char타입의 배열로 String을 표현한다. char배열과 문자열의 구분은 문자열의 마지막에 '\0'의 유무로 판단한다. char배열의 끝에 모두 0으로 채우는 '\0'이 있으면 문자열로 인식하고, 그렇지 않으면 char배열로 인식한다. '\0'은 숫자로 해석 시 0이고, char로 해석 시 null로 해석하면 된다. char배열에서 '\0'을 만나면 뒤에 남아있는 요소에 상관없이 해석을 끝마친다. 즉, 널문자를 이용하면 문자열을 파싱할 수 있다. char str[10]; scanf("%s", str); printf("%s", str); scanf를 사용해 입력받을 때 문..
[C] 배열
[C] 배열
2022.03.28C에서는 자바와 배열의 선언 방식이 다르다. int arr[100]; 자바에서는 타입 뒤에 []가 와도 괜찮았지만, C에서는 변수명 뒤에 []를 붙여야 한다. 또, C에서는 객체지향 개념이 적용되지 않아서 저렇게 선언 후 바로 배열의 요소에 접근할 수 있다. int arr[100]; arr[1] = 12; 자바에서는 배열을 객체로 다루기 때문에 메모리 공간에 대해서 쉽게 이해할 수 있었다. 반면 C에서는 배열에 대해 생각해야 할 부분이 좀 있다. &는 주소를 의미한다고 보면 된다. rabbit[2] = 3; 같은 코드를 실행할 때, 배열의 시작인 rabbit[0]의 시작 부분(주소로는 100)에서 int사이즈의 크기인 4와 2를 곱한 값을 더해서 주소를 찾고, 값을 넣어준다. C에서 배열은 연속된 메모리..
[C] 함수 간 소통 / 재귀
[C] 함수 간 소통 / 재귀
2022.03.22소통 전역변수를 이용하면 함수들 간에 정보를 교환할 수 있다. 하지만... 전역변수와 지역변수의 이름이 같을 때는 전역변수에 접근할 수 없고, 어떤 함수가 전역변수에 접근했는지 판단하기 어렵기 때문에 디버깅도 어렵다. 그러므로 두 함수 사이에서 소통하는 방법이 합리적이다. 지역 변수를 복사해서 건네주고, 또 리턴 값을 돌려받는 방식으로 함수들 간의 소통을 구현할 수 있다. 이 때 리턴할 수 있는 인자는 하나뿐이기에 이 부분에 주의해서 코드를 작성하자. 재귀 알고리즘 문제를 풀 때 분할 정복 방법으로 푸는 경우가 많다. 이 때 자신을 호출하는 재귀함수를 많이 사용한다. 속도와 성능 측면에서는 불리하지만, 코드를 간결하게 작성할 수 있을 경우 사용한다. 재귀함수는 base case부분과 재귀 호출 부분으로 ..