차근차근/C
zero array
검색어 :zero array , zeros()
Mat::zeros
Returns a zero array of the specified size and type.
- C++: static MatExpr Mat::zeros(int ndims, const int* sz, int type)
Parameters: - ndims – Array dimensionality.
- rows – Number of rows.
- cols – Number of columns.
- size – Alternative to the matrix size specification Size(cols, rows) .
- sz – Array of integers specifying the array shape.
- type – Created matrix type.
The method returns a Matlab-style zero array initializer. It can be used to quickly form a constant array as a function parameter, part of a matrix expression, or as a matrix initializer.
Mat A;
A = Mat::zeros(3, 3, CV_32F);
In the example above, a new matrix is allocated only if A is not a 3x3 floating-point matrix. Otherwise, the existing matrix A is filled with zeros.
소스를 보던 중 나온 함수.
지정된 크기와 종류의 제로 배열을 돌려준다고 한다.
친절하게 알려줘도 이해 못해서 찾아봤다.
Size가 0인 배열은 도대체 무엇에 쓰이는 물건인가?
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNO=20&no=7804
강좌를 시작하기 전에..
정말 오랜만에 강좌를 하나 올립니다.
특히나 아이디가 고임에서 본명으로 바뀐 뒤로는 정말 처음인 듯 싶은데..
예전에는 나름대로 정열적이어서 후다닥 썼던 것 같은데..
눈치도 좀 보이고, 머리가 둔해져서 설명을 어떤 식으로 해야할지도 참 한참을 고민했던 것 같습니다.
여전히 고임의 강좌는 극 초보자를 위한 강좌입니다.
아시는 분들은 다 알만한 내용이라서 봐봐자 의미도 없으니 살짜쿵 넘어가 주시기 바랍니다.
강좌에서는 반말체를 사용했습니다. 기분 나쁘실 분들을 위해 미리 사과드립니다.
고임.
ps. 이제 이곳도 새로운 분들이 많아져서 아는 분이 거의 없네요. ㅎㅎ
Size가 0인 배열은 도대체 무엇에 쓰이는 물건인가?
작성자 고임
최초 작성일 : 2007년 11월 30일 ~
마지막 작성일 : 2007년 12월 5일
- 들어가기
우리는 컴퓨터 언어의 표준을 따르며 험난한 코딩의 나날을 보내고 있다. 매일 매일 새로운 기술 홍수 속을 키보드와 마우스로 헤쳐나가며, 코딩의 앞길마다 떨어지는 버그를 씹어 삼키며, 코딩의 기술 연마하고 있다.
고임 역시 중후한 표준의 사명을 따르며, 코딩을 하던 중, 컴파일러는 내게 다음과 같은 경고를 보내왔다.
warning C4200: nonstandard extension used : zero-sized array in struct/union (.cpp)
물론 실행하는데는 문제가 없으나 컴파일러가 도전장을 내밀듯이 불쑥 튀어나온 경고는 기분이 나쁘지 않는가?
한동안 위와 같은 경우를 겪어보지 않아. 적잖히 당황을 했지만, 이내 몇 년전 구글의 C 포럼의 쓰레드에서 사이즈가 0인 배열의 글타래를 기억해냈다. 물론 비표준이었는지 아니었는지 기억이 가물가물하여 내가 알고 있는 프로그래머 중 가장 파워풀한 지식과 다이나믹한 코딩 스킬을 가지고 계신 분에게 여쭈어보았다.
고임 : 사이즈가 0인 배열은 표준이 아니죠?
그분 : 표준은 아니지만 대형 벤더들은 전부 지원해요.
그때의 다시금 기억을 되살리려 노력을 한다. 그러나, 금붕어도 울고갈 기억력의 소유자인 고임은 “후후 내가 기억할리가 없잖아!”라며.. 너무 쉽게 인정해버리고 자료를 찾아본다. 그러나 별다른 자료가 없다. 예전에 보았던 구글에서의 쓰레드는 어디로 갔는지 잘 찾질 못하겠고.. 다만 기억이 있는 것은 그 글타래에서 나왔던 이야기 중에 이런게 된다. 정도.. 였던 걸로 기억이 된다. 그 당시에는 사실 별 관심은 두지 않았다.
그리하여 내가 하고 있는 프로젝트에서 해당 경고가 나온 줄을 찾아본다. 그것을 기반으로 하여 사이즈가 0인 배열의 정체를 파혜쳐 보기로 하였다.
이런 식의 강좌 글은 느낌 상으로 수백년만에 다시 써보는 것 같아, 조금은 설레이나.. 할 것이 태산인 상황에서 이런 짓을 하니 조금은 눈치가 보이기는 한다.
허나, 벤더사가 자신있게 내놓은 라이브러리에 비표준이 존재한다는 것에 무슨 의미가 있지나 않을까? 하는 강항 의구심을 해결하기 위하여 이 거대하고도 멋지고도 다 알고 나면 허무 개그를 본 듯한 주제를 가지고 달려보도록 하자.
- 사이즈가 0인 배열의 비표준의 경고와 에러 사이.
사이즈가 0인 배열이라고 하는 것은 단순히 다음과 같다.
int nZeroArray[0];
즉 배열을 선언하는 순간 그 배열의 크기가 0이라는 것을 이야기 한다.
그러나 이것은 비표준이다. 따라서 당연히 에러가 발생이 된다. 상식적으로 크기가 0인 배열을 선언한다는 것이 말이 안되는 것 아닌가? 사이즈가 0인데 뭐하러 선언하는가?
그래서 우리의 컴파일러께서는 다음과 같은 에러 문장을 내주신다.
error C2466: 상수크기 0의 배열을 할당할 수 없습니다.
의역하자면 “장난하냐? 크기가 0인 배열을 어디에 위치시키라고?” 즉, 크기가 없기에 실존할 수 없다는 철학적인 메세지를 주시는 것이다.
여기서 우리가 눈치를 채야 할 것은 바로 사이즈가 0인 배열은 독립적으로 사용할 수 없다 라는 사실이다.
자 반복 학습이 중요하다.
“사이즈가 0인 배열은 절대 독립적으로 사용할 수 없다.”
자 그렇다면 이건 어디서 사용해야하는 것일까?
이것은 눈치가 빠른 분들은 아시겠지만, 구조체 공용체 클래스에서 사용할 수 있다. 뭐 사실 그것 밖에 더 있겠는가? -_-;
그 이유는 나중에 이야기 하기로 하고, 다음을 보도록 하자.
union UZeroArray{
int nZeroArray[0];
};
struct SZeroArray{
int nZeroArray[0];
};
class CZeroArray{
int nZeroArray[0];
};
이 세 개의 구조체, 공용체, 클래스(이거 한글 표현이 뭐지?)안에는 멤버로써 크기가 0인 배열을 갖는다.
이 삼총사는 컴파일링의 시험에 간신히 합격하시며, 다음과 같은 코멘트를 달고 빌드가 되신다.
warning C4200: 비표준 확장이 사용됨: 구조체/공용구조체의 배열 크기가 0입니다.
UDT에 크기가 0인 배열이 있는 경우 복사 생성자 또는 복사 할당 연산자를 생성할 수 없습니다.
이 경고는 봐주긴 봐주는데. 일반적으로 사용하면 죽어! 라는 의미를 갖는다. 따라서 사이즈가 0인 배열은 용도가 매우 좁으니까, 너가 신경써서 사용하라는 이야기이다.
자 여기서 강좌 예제의 범위를 축소하기로 한다. 공용체나 클래스의 예제는 과감히 건너뛰기로 하고 구조체에 대해서만 살피도록 하겠다. (알고 싶은 분은 직접 코딩해서 알아보시길.)
struct SEndZeroArray{
int ndummy;
int nZeroArray[0];
};
struct SStartZeroArray{
int nZeroArray[0];
int ndummyEnd;
};
struct SMiddleZeroArray{
int ndummyStart;
int nZeroArray[0];
int ndummyEnd;
};
struct STwoZeroArray{
int ndummy;
int nZeroArray1[0];
int nZeroArray[0];
};
위의 크기가 0인 배열의 예제들이 아주 훌륭히 짜여져 있다. 여기서 컴파일 에러를 내지 않는 것은 무엇일까?
컴파일을 해보면 알겠지만, 첫 번째 예제만이 무난히 컴파일링을 통과하시게 된다. 나머지 세 개의 예제는 다음과 같은 에러를 당하시게 된다.
error C2229: struct 'SstartZeroArray'에 크기가 0인 잘못된 배열이 있습니다.
즉, 사이즈가 0인 배열의 멤버는 공용체, 구조체, 클래스의 선언에서 가장 마지막에 선언을 해줘야하며, 해당 구조체, 공용체, 클래스에서 유일한 멤버변수여야 한다는 이야기이다. 여기서 매우 중요한 이야기가 두 개나 나오게 된다. 자 기억하자!!
“사이즈가 0인 배열은 공용체, 구조체, 클래스 안에서 가장 마지막 멤버 변수로 선언되어야 한다.”
“사이즈가 0인 배열이 선언이 되는 공용체, 구조체, 클래스 안에서 오직 하나여야 한다.”
여기까지 사이즈가 0인 배열을 에러를 피하기 위해 어떤 식으로 선언을 해야할지를 알아보았다. 세줄로 요약하면 다음과 같다. 이것을 명심하고 다음 단계로 넘어가기로 하자.
“사이즈가 0인 배열은 절대 독립적으로 사용할 수 없다.”
“사이즈가 0인 배열은 공용체, 구조체, 클래스 안에서 가장 마지막 멤버 변수로 선언되어야 한다.”
“사이즈가 0인 배열이 선언이 되는 공용체, 구조체, 클래스 안에서 오직 하나여야 한다.”
- 버그의 경계를 넘어..
자 여기서 부터는 왜 이런 비표준을 여전히 아직도 쓰고 있는지에 대해서 알아보겠다. 라고는 했지만. 역으로 추적하면서 이 강좌를 쓰는 것이므로 역사적인 배경은 전혀 알 수 없다. 그리고 역시 C99이나 새로 계정된 C++ 표준에 반영이 되려 했는지도 알 수 없다. 최근에 보았던 C99에 자료에서는 보지 못했던 것 같다. 사실 이런 기법에 대해서 관심이 없었다고 하는 것이 더 맞는 표현이겠지만, 말이다.
기존에 MS가 제공하는 라이브러리의 헤더에서 보여지는 크기가 0인 배열의 흔적을 거꾸로 찾아보며 느낀 점을 바탕으로 만들어진 예제를 가지고 왜 이런 비표준을 아직도 사용하는지에 대해서 이야기 해보도록 한다. (사실 크기가 0인 배열을 활용할 수 있는 기법은 하나 밖엔 없을 것으로 확신한다. )
자 시작해 보도록 합시다.
아래 예제는 일반적으로 어떤 정보 목록의 크기가 정적으로 정해져 있지 않고, 동적으로 변경이 될 가능성이 높을 때 사용되는 일반적인 정보 목록 관리 방법과 크기가 0인 배열을 이용한 정보 목록 방법을 비교하여, 크기가 0인 배열을 사용하면 어떤 이득이 있는지에 대해 알아보는 시간을 갖도록 하겠다.
다시 쉬운 문장으로 이야기 하자면, 아.. 예전엔 쉽게 잘(-_-;) 썼던 것 같은데. 음.....
예를 들어,
공연 티켓을 사는 사람들의 성향을 알아보기 위한 프로그램을 설계한다고 가정하자.
(여기서 Db를 사용하는 건 제외합시다.)
기본적으로 공연 티켓을 사는 사람들의 정보는 이름, 나이, 구매티켓수, 지역, 구입처 등등이 있을텐데.
구매하는 사람에 대한 정보를 담을 구조체가 필요할테고,
이 정보를 통합 관리할 구조체가 또 필요하다.
바로 이런 경우의 상황에 대해서 앞으로 논의할 것이다.
아래 예제를 보시면서,
"기술적으로 저건 올바른 방법이 아니네."
"이렇게 해야 더 효율적이네."
"저게 무슨 일반적인 방법이야?"
"크기가 0인 배열은 됐구요. 도는 믿고 계십니까?"
"저 예제는 어디서 본 것 같아? 당신 표절 쟁이지?"
라고 평하실 분들.. 여기서 읽기를 그만두시길 바랍니다.
더 읽어봤자 서로 정신건강에 해롭습니다.
다시 한번 강조하지만, 이 강좌는 "크기가 0인 배열이 무엇인가?"를 알아보는 것이다.
설명하기 편하게 UNICODE는 사용하지 않았다는 걸 미리 이야기한다.
예제의 빌드 환경
OS : Windows XP Professional
Complier : VS2005
CPU : Intel Core 2 6600
typedef struct tagVirtualDeviceInfo
{
int DummyN;
char DummyString[30];
float DummyFloat;
}VirtualDeviceInfo, * pVirtualDeviceInfo;
Device의 정보를 담을 구조체.
typedef struct tagVirtualDevice
{
int DeviceSize; // 가상장치의 갯수.
pVirtualDeviceInfo Info; // 가상장치의 정보에 대한 주소
}VirtualDevice, *pVirtualDevice;
Device 정보를 통합 관리할 구조체( 일반적인 방법)
이 데이타 구조는 여러개의 가상 장치의 정보를 가상 장치 정보의 주소를 담을 수 있도록 했으며, 데이타 구조에서 관리되는 가상 장치의 정보의 갯수도 기록할 수 있겠금 구성되어있다.
이 구조가 우리가 흔히 접할 수 있는 구조이며, 이런 형태로 구성하는 것이 거의 정석이라 할 수 있겠다.
typedef struct tagVirtualDeviceZeroSize
{
int DeviceSize; // 가상 장치의 갯수.
VirtualDeviceInfo Info[0]; // 바로 이 분이 이 강좌의 주인공이심.
}VirtualDeviceZeroSize, * pVirtualDeviceZeroSize;
Device 정보를 통합 관리할 구조체( 크기가 0인 배열을 이용한 방법)
이 데이타 구조는 2번째의 데이타와 구조와 마찬가지이지만, 가상 장치 정보를 기록하는 멤버 변수가 크기가 0인 배열로 선언이 되어 있다.
처음 보는 사람들은 아마 “이 뭐병” 이란 단말마를 내실지 모르겠으나, 이 코드는 굳건히 컴파일링을 통과하십니다.
01 : void ZeroLengthArrayTest(void)
02 : {
03 : int nDeviceNumber = 2;
여기서 가상 장치가 2개만 있다고 생각하기로 하자.
04 : int nSizeVirtualDeviceInfo = sizeof(VirtualDeviceInfo);
05 : int nSizeVirtualDevice = sizeof(VirtualDevice);
06 : int nSizeVirtualDeviceZero = sizeof(VirtualDeviceZeroSize);
07 : int nSizeVirtualDeviceMem = nSizeVirtualDevice;
08 : int nSizeVirtualMemZero = sizeof(VirtualDeviceZeroSize) + sizeof(VirtualDeviceInfo)*nDeviceNumber;
여기서 우리는 VirtualDevice 크기가 8바이트이고, VirtualDeviceZeroSize의 크기가 4바이트 라는 것을 눈여겨봐야한다. VirtualDeivce의구조는Device의 목록의 갯수와 DeviceInfo의 정보를 가리키는 포인터로 구성되어 있으므로, 당연히 8바이트가 되게 된다. (물론 32비트 OS 상에서 32비트 어플리케이션을 제작할때의 이야기이다. 설마 이런 것도 트집 잡으려나? )
VirtualDeviceZeroSize는 Device의 목록의 갯수를 저장하는 변수가 4바이트 DeviceInfo의 정보를 저장하는 배열의 크기가 0이다.
이런 걸 처음 보는 사람은 리엑션을 크게 취해주도록 하자. 그래야 기억에 남는다고 하더라.
허허 그렇담 VirtualDeviceInfo Info[0]; 는 어디에 저장이 될 것인가?
그 이야기는 잠깐 뒤에서 이야기하도록 한다.
일반적인 방법: 구조체 초기화
09 : pVirtualDevice pVD1 = new VirtualDevice;
Virtual Device의 목록을 관리할 데이타를 생성합니다.
10 : VirtualDeviceInfo* pVirtualDeviceMemInfo = new VirtualDeviceInfo[nDeviceNumber];
11 : memset(pVirtualDeviceMemInfo, 0, nDeviceNumber* sizeof(VirtualDeviceInfo));
Virtual Device의 정보를 기록할 메모리를 확보하고 초기화한다.
12 : pVD1->DeviceSize = nDeviceNumber;
디바이스의 갯수를 기록한다.
13 : pVD1->Info = pVirtualDeviceMemInfo;
VirtualDeviceInfo를 가리키는 멤버 변수를 초기화시킵니다. 이 부분은 크기가 0인 배열을 이용한 방법에선 필요 없는 코드가 된다.
크기가 0인 배열을 이용한 방법: 구조체 초기화
14 : void* pVirtualDeviceMemZero = new BYTE[nSizeVirtualDeviceMemZero];
15 : memset(pVirtualDeviceMemZero, 0, nSizeVirtualDeviceMemZero);
위와는 다르게 Virtual Device의 목록을 관리할 데이타와 Virtual Device의 정보를 나타내는 데이타의 크기를 선형적으로 한꺼번에 생성하고 초기화하는 것에 유의하며 봅시다.
이 부분이 바로 크기가 0인 배열을 사용하는 이유가 되며, 일반적인 방법과는 달리 VirtualDeviceInfo
를 가리키는 멤버 변수를 초기화 할 필요가 없다.
16 : pVirtualDeviceZeroSize pVD2 = (pVirtualDeviceZeroSize) (pVirtualDeviceMemZero) ;
자 위에서 생성한 메모리를 형변환하여 pVirtualDeviceZeroSize 형의 변수에 대입해보자. 이때 VirtualDeviceInfo를 가리키는 Info의 주소를 살펴보면, 정확히 pVD2라는 변수가 할당된 메모리 위치의 바로 다음을 가리키게 된다.
호오 놀랍지 않은가? 일반적인 방법의 13번째 줄 처럼 Info 변수에 초기화도 하지 않았는데 말이다.
이것이 가능한 이유는 바로 배열이 선형적인 메모리를 갖는다는 특성 때문이다.
위의 그림을 보면.. pVD2의 메모리 위치는 0x00ee9f30이고, pVD2->Info가 가리키는 메모리 위치는 0x00ee9f34이다. 정확히 4만큼의 offset을 가지고 있는 것을 확인 하도록 하자.
17 : pVD2->DeviceSize = nDeviceNumber;
디바이스 갯수를 기록한다.
일반적인 방법 : 데이타 입력
18 : pVD1->Info[0].DummyN = 0x11;
메모리를 알아보기 쉽게 하기 위해 0x11을 삽입하도록 하자.
19 : memcpy(pVD1->Info[0].DummyString, "Virtual Device 1", sizeof("Virtual Device 1") + 1);
20 : pVD1->Info[1].DummyN = 0x22;
21 : memcpy(pVD1->Info[1].DummyString, "Virtual Device 2", sizeof("Virtual Device 2") + 1);
크기가 0인 배열을 이용한 방법: 데이타 입력
22 : pVD2->Info[0].DummyN = 0x11;
23 : memcpy(pVD2->Info[0].DummyString, "Virtual Device Zero 1", sizeof("Virtual Device Zero 1") + 1);
24 : pVD2->Info[1].DummyN = 0x22;
25 : memcpy(pVD2->Info[1].DummyString, "Virtual Device Zero 2", sizeof("Virtual Device Zero 2") + 1);
비록 크기가 0인 배열이라고 선언을 하였더라도, 배열의 이름인 Info가 배열이 시작되는 지점을
가리키는 주소가 되므로, pVD2 메모리 위치 뒤에 VirtualDeviceInfo 크기를 기준으로 배열의 크기가
확보된 상태에선 배열처럼 사용이 가능하다.
또 다른 장점으로는 어셈 코드가 간단해진다는 장점이 존재한다.
구조체에서 맴버 변수로 접근을 할때는 구조체 변수의 주소를 알아내고 나서, 해당 구조체의 멤버 변수의 주소를 알아낸 뒤 접근을 하게 되는데.
크기가 0인 배열을 이용하게 되면, 크기가 0인 멤버 변수가 메모리에 생성 되지 않기 때문에 Info란 맴버 변수는 코드상으로만 존재할 뿐 컴파일을 하게 될 때는 그저 offset으로만 인식하게 된다.
따라서 위의 일반적인 방법보다 조금은 명령어가 적게 들게 된다.
26 : delete pVD1;
27 : delete [] pVirtualDeviceMemInfo;
28 : delete [] pVirtualDeviceMemZero;
37 : }
정리하자면 크기가 0인 배열은 선형적으로 크기가 변하는 경우에 사용할 수 있는 일종의 치트 문법이다.
배열이란 문법적인 특징을 아주 치사하게 이용하고 있다고나 해야 할까?
이걸 처음 이용한 사람이 누구인진 모르겠으나, 이 점에 대해선 기립박수를 쳐주고 싶다. .
뭐 어찌 되었던, 크기도 작고, 명령어도 적게 쓰면서 동일한 효과를 내게 되었으니 말이다.
C언어에서 기존에 많이 사용이 되고 있어서, C++에서는 C와의 호환 유지 차원에서 봐 준 것 같다.
사실 마이크로 콘트롤러 래벨로 내려가면 막강한 기법이라고 생각이 든다.
하지만, 트릭처럼 사용되는 문법이기 때문에 언제까지 이것을 유지할지는 확신은 들지 않는다.
문법상으로 명백히 틀린 부분은 없으나, 버그의 경계선에서 왔다 갔다 하는 코드를 유지해야 하는 것도
점점 강화되고 있는 문법 성향에 안 맞는 것 같기도 하고,
C언어는 모르겠지만 아마 앞으로는 C++ 언어에선 사라질지도 모를 일이라고 조심스레 예견해본다.
부록 - 예제 코드 전문
typedef struct tagVirtualDeviceInfo
{
int DummyN;
char DummyString[30];
float DummyFloat;
}VirtualDeviceInfo, * pVirtualDeviceInfo;
typedef struct tagVirtualDevice
{
int DeviceSize; // 가상장치의 갯수.
pVirtualDeviceInfo Info; // 가상장치의 정보에 대한 주소
}VirtualDevice, *pVirtualDevice;
typedef struct tagVirtualDeviceZeroSize
{
int DeviceSize; // 가상 장치의 갯수.
VirtualDeviceInfo Info[0];
}VirtualDeviceZeroSize, * pVirtualDeviceZeroSize;
void ZeroLengthArrayTest(void)
{
int nDeviceNumber = 2;
int nSizeVirtualDeviceInfo = sizeof(VirtualDeviceInfo);
int nSizeVirtualDevice = sizeof(VirtualDevice);
int nSizeVirtualDeviceZero = sizeof(VirtualDeviceZeroSize);
int nSizeVirtualDeviceMem = nSizeVirtualDevice;
int nSizeVirtualMemZero = sizeof(VirtualDeviceZeroSize) + sizeof(VirtualDeviceInfo)*nDeviceNumber;
pVirtualDevice pVD1 = new VirtualDevice;
VirtualDeviceInfo* pVirtualDeviceMemInfo = new VirtualDeviceInfo[nDeviceNumber];
memset(pVirtualDeviceMemInfo, 0, nDeviceNumber* sizeof(VirtualDeviceInfo));
pVD1->DeviceSize = nDeviceNumber;
pVD1->Info = pVirtualDeviceMemInfo;
void* pVirtualDeviceMemZero = new BYTE[nSizeVirtualDeviceMemZero];
memset(pVirtualDeviceMemZero, 0, nSizeVirtualDeviceMemZero);
pVirtualDeviceZeroSize pVD2 = (pVirtualDeviceZeroSize) (pVirtualDeviceMemZero) ;
pVD2->DeviceSize = nDeviceNumber;
pVD1->Info[0].DummyN = 0x11;
memcpy(pVD1->Info[0].DummyString, "Virtual Device 1", sizeof("Virtual Device 1") + 1);
pVD1->Info[1].DummyN = 0x22;
memcpy(pVD1->Info[1].DummyString, "Virtual Device 2", sizeof("Virtual Device 2") + 1);
pVD2->Info[0].DummyN = 0x11;
memcpy(pVD2->Info[0].DummyString, "Virtual Device Zero 1", sizeof("Virtual Device Zero 1") + 1);
pVD2->Info[1].DummyN = 0x22;
memcpy(pVD2->Info[1].DummyString, "Virtual Device Zero 2", sizeof("Virtual Device Zero 2") + 1);
delete pVD1;
delete [] pVirtualDeviceMemInfo;
delete [] pVirtualDeviceMemZero;
}
[Matlab / 매트랩] 강의 2번째
http://engi-agora.tistory.com/5
2 by 3 크기의 1을 원소로 가지는 행렬 A를 만들기 위해서는 어떻게 입력을 해 줘야 할까요?
두구둑두구두굳구두구구구두굳구ㅜ
네 바로 요렇게 해주면 됩니다.
>> A=[1 1 1; 1 1 1]
참 쉽죠잉?
근데 후후후후후후후후후
100 by 3 크기의 1을 원소로 가지는 행렬 A를 만들기 위해서는 어떻게 입력을 해줘야 할까요?
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
>> A=[1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 ...............a;klsjdfopij!@^!@#$%$&QE%!#y]
이렇게 하면 되겠죠잉?ㅋㅋㅋㅋㅋㅋㅋㅋ
만들어 보세요ㅋㅋㅋㅋㅋㅋ
1000 by 1000은?ㅋㅋㅋㅋ
ㅋㅋ
ㅋ
화내지마요. 사랑하니까..
이런 화가나는 경우를 대비해서 좋은 명령어가 있습니다.
바로 ones라는 명령어 인데요.
ones(m,n)을 넣어주면 m by n 크기의 1을 행렬의 원소로 가지는 행렬이 만들어 지게 됩니다.
한번 보실까요?
>> A=ones(3,5)
A =
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
네 상큼하게 나와줍니다.
1000 by 1000같은 경우는
A=ones(1000,1000)을 입력해주시면 돼요.
근데 요런 경우는 command창에 너무나도 많은 숫자가 뜨기 때문에,
A에 입력은 해주지만 결과는 표시해 주고 싶지 않을 경우
세미콜론 " ; " 를 입력해주시면 됩니다.
이런 식인거죠.
>> A=ones(1000,1000);
그러면 요렇게 되는 것을 확인할 수 있습니다.
입력창에는 아무것도 뜨지 않죠?
옆에 workspace에는 A가 1000,1000의 크기로 행렬이 있다는 것을 보여주고 있습니다.
즉 입력창에는 나타나지 않았지만 A라는 행렬이 만들어 진 셈이죠.
요렇게 ones와 비슷하게 행렬은 만들 수 있는 명령어가 더 있습니다.
zeros(m,n)
eye(m)
zeros는 뭔지 쉽게 알 수 있겠죠?
m by n의 크기로 성분이 0인 행렬을 만들어 주는 명령어입니다.
twos 같은건 없어요. zeros, ones만 있는 것 같습니다....(는 생각?)
eye는 identity matrix 즉, 단위행렬을 만들어주는 명령언데요,
행렬의 대각 성분이 1, 나머지는 0인 행렬을 만들어 주는 겁니다. 여러모로 편리해요 알아두시면.
한번 만들어 보겠습니다.
>> A=eye(2)
A =
1 0
0 1
네 이런식입니다아아.
참 쉽죠잉?
'차근차근 > C' 카테고리의 다른 글
VB2013이랑 mysql연동 (0) | 2015.07.08 |
---|---|
이클립스 | C/C++ | opeCV | Tesseract OCR => 1 (2) | 2015.03.10 |
win8 | vs2010 | tesseract-3.01 | leptonica-1.71 (0) | 2015.02.24 |
GIMP실행하기 (0) | 2015.01.02 |
CString , char , LPSTR ... 형변환 (0) | 2014.12.02 |