2015. 3. 7. 19:46ㆍ창고
오프라인 토론 - 혼자 연구하는 C/C++ 정리
11장 배열과 포인터
c에는 실제로 2차원 배열은 없다
- 왜냐면 메모리는 선형 구조이기 때문이다.
메모리상에는 선형으로 정의된다.
배열은 사실 포인터다. 첨자 연산은 내부적으로 포인터의 값 증가.
- 서기가 적어놓은 것이긴 하지만. 배열이 포인터란 말은 조금 이상하지싶다.
배열 접근의 내부적 연산이 배열과 같다는 것이지 배열이 포인터라고 표현하는건 조금 아닌거같다.
배열의 배열명은 시작 주소를 가지는 포인터 상수이다.
ar[10]이란 것이 있다면 컴파일러는 내부적으로 이것을 *(ar+10)으로 바꿔서 접근한다.
그렇기 때문에 일반적으로 배열이 포인터보다 아주 살짝 느리다.
포인터 배열 = 요소가 포인터인 배열. 끝.
이중 포인터 배열 **ptr[3]이라면 **ptr을 3개 담아놓는 배열. 끝.
배열 포인터 = 배열을 가리키는 포인터. 2차원 이상에서만 의미가 있다.
이차원 동적 배열 할당. 안된다. 이중 포인터 써라.
&ar. ar과 &ar은 다르다.
문자열 상수 - 정적 데이터 영역에 저장된다.
함수에 넘겨야하는 것이 이차원 이상의 배열인 경우, 이차원 포인터를 넘기면 안된다. (타입을 맞춰줘야한다.)
- 함수에 이차 배열을 넘기는 경우 포인터 배열, 배열 형태로 받는 것이 가장 깔끔하다고 생각한다.
func(char* arr[], char arr[][])
구조체란 뭔가? -> 동형 , 이형의 기본 자료형을 관리할 수 있는 자료형
구조체 패딩. 데이터를 넣는 순서에 따라서 구조체의 크기가 바뀔 수 있다!
typedef struct
{
int a;
double d;
char b;
short c;
}PT;
typdef를 하게 되면 이렇게 태그명 없이도 사용할 수 있다.
단순히 struct로 할 경우 PT는 그냥 변수.
서기가 조금 빼먹은 내용
비트 필드
- 구조체에서 변수의 비트를 쪼개서 값을 넣는다.
활용? 교수님이 말씀해주신 직업 - 장비 검출 플래그용으로?
그 외에는 활용할 방법은 연구해봐야된다.
온라인 토론 - 포인터, 구조체, 배열
포인터의 정의
- 운영체제로부터 메모리 공간 어딘가에 자료형에 관계없이 4바이트의 메모리 공간을 할당받고
그 주소 위에 a라는 방을 만들고 그 안에는 쓰레기 주소값이 들어있다.
int* imsi; *imsi = 1024; 가 되는가?
- 쓰레기 주소값이 들어 있는 상태에서 그 곳에 정수를 넣으면 알 수 없는 메모리에 값을 넣게 된다.
컴파일 시점에는 아무 문제 없이 돌아가지만 런타임 시에는 초기화되지 않는 변수 에러가 난다.
포인터는 왜 타입이 존재하는가?
- 두 가지 이유. 첫 번쨰는 포인터가 가리키는 곳을 해석하기 위해서. 두 번째는 포인터 연산을 위해서.
간단하게 해석과 연산을 위해.
포인터 배열 vs 배열 포인터
- 포인터 배열은 배열, 배열 포인터는 포인터.
포인터 배열 - 그 원소가 포인터인 배열.
배열 포인터 - 배열의 번지를 담는 포인터 변수.
char* str vs char str[]
- 정적데이터에 들어가는 문자열 상수가 있다고 가정했을 때,
포인터 변수는 그 주소를 직접 가리키게 되고 배열은 그 값을 복사하여 문자열을 넣는다.
그래서 포인터 변수로는 문자열 내부를 수정할 수 없고 배열에선 문자열을 수정할 수 있다.
포인터 변수 초기화 시 왜 NULL을 쓰는가?
- 포인터 변수가 데이터 저장공간을 지정하지 않았다는 명시이다.
NULL은 실제로 0으로 정의된 정수 상수지만 이 상수는 아주 특별하게 포인터 변수와 연산을 허용한다.
BSS에 대한 재논란
- 포인터책에서 BSS영역이 전역변수 한정이라는 글을 발견.
초기화 하지 않으면 BSS영역에 메모리 공간이 잡히고 0으로 초기화 된다. (일단 결론)
조금 더 논의가 필요한 부분.
*ptr++에 대한 이해, 논란
- 이해 : ptr의 값을 먼저 접근하고 ptr의 포인터를 한 번 증가한다.
- 논란 : 연산자 우선순위로 *가 먼저냐 ++이 먼저냐. 갑론을박
"++가 연산자 우선순위가 높기 때문에 ++가 먼저 실행되지만
실제로 후치연산이기 때문에 *ptr이 먼저 실행되고 포인터가 증가."
이 생각이 맞다고 생각했는데 또 어셈블리 코드를 봐선 또 그게 아닌거같고....
조금 더 논의가 필요한 부분.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | getnumber = *ptr++; //< ptr의 주소를 eax에 대입 00AA3C42 mov eax,dword ptr [ptr] //< eax의 값을 ecx에 대입 00AA3C45 mov ecx,dword ptr [eax] //< ecx에 있는 값을 getnumber에 대입(즉 getnumber = 1) 00AA3C47 mov dword ptr [getnumber],ecx //< ptr의 주소를 edx에 대입 00AA3C4A mov edx,dword ptr [ptr] //< edx에 4를 더함 00AA3C4D add edx,4 //< edx의 값을 ptr에 대입 00AA3C50 mov dword ptr [ptr],edx //< 마지막에 포인터의 이동이 된다.(edx는 ptr의 주소에서 4를 증가 //시킨 주소 값을 갖고있으므로 | cs |
'창고' 카테고리의 다른 글
국기3기 정규수업 8일차 메모 (0) | 2015.03.09 |
---|---|
20150308 토론정리 (0) | 2015.03.08 |
혼자 연구하는 C/C++ 13장 정리(구조체) (0) | 2015.03.07 |
20150306 토론정리 (2) | 2015.03.07 |
국기3기 정규수업 6&7일차 메모 (0) | 2015.03.07 |
(과제)입출력 함수들 비교 (0) | 2015.03.06 |
국기3기 정규수업 5일차 (0) | 2015.03.05 |