typeof 는 gcc의 확장된 기능으로, 해당 변수의 타입을 반환하는 역할을 하는 매크로 함수이다.

예제 코드)
#include <stdio.h>

int main()
{
    char s1;
    typeof(s1) s2;

    unsigned char u1;
    typeof(u1) u2;

    s2 = 0xff;
    u2 = 0xff;

    printf("s2 = %d\n", s2);
    printf("u2 = %d\n", u2);
    return 0;
}

결과)
s2 = -1
u2 = 255


strlen 함수를 사용시 인자로 NULL 포인터를 넘기면 segmentation fault 가 발생한다.
이는 0 번지로 가서 문자 개수를 세는 것으로 생각되며, 0번지를 참조 하려고 하기 때문에 segmentation fault가 발생하는 것 같다.




////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

"\0" 문자열로 바꿔주면 segmentation fault가 발생하지 않는다.



 

매크로 함수

#1. 매크로 함수란?

#2. 괄호 속에 있는 이유는?

#3. 매크로와 함수 및 템플릿의 비교

#4. 인라인 함수란?

#5. 문자열 조작

#6. 문자열화 연산자

#7. 결합연산자

#8. 내장매크로

#9. assert()

 

#1. 매크로 함수란? (a)

  - 매크로 함수는 #define을 사용하여 만들어지는 기호이다. 이 기호는 함수처럼 하나의 인수를 가진다.

  - 전처리기는 특정 인수가 무엇이든 상관없이 치환 문자열로 대치한다.

  1.        #define TWICE(x) ( (x) * 2 )

  - 매크로는 하나 이상의 매개 변수를 가질 수 있고, 반복해서 사용할 수 있다.

  1.        #define MAX(x,y) ( (x) > (y) ? (x) : (y) )
  2.        #define MIN(x,y) ( (x) < (y) ? (x) : (y) )

  [주의] 매크로 함수 정의에서 매개 변수 목록에 대한 여는 괄호가 매크로 이름 바로 다음에 빈칸 없이 곧바로 이어져야 한다.

 

#2. 괄호 속에 있는 이유는? (b)

  - 전처리기는 치환 문자열의 인수 주위에 괄호가 있을 것을 요구하지 않지만, 괄호는 복잡한 값을 매크로에 전달할 경우 원하지 않는 결과가 나오는 것을 방지하는데 도움을 준다.

#3. 매크로와 함수 및 템플릿의 비교 (c)

  - 문제점

    ① 매크로가 커질 경우 혼란스러워질 수 있다.

    ② 사용한 곳에서 곧바로 인라인으로 확장된다.

    ③ 매크로가 컴파일러에서 사용하는 중간 소스 코드에 나타나지 않는다. 대부분의 대버거에서 사용할 수 없다.

    ④ 형에 안전하지 않다.

#4. 인라인 함수란? (d)

  - 확장인라인 : 함수의 내용이 함수가 호출된 코드에 삽입되는 것을 말한다.

  1.     inline unsigned long Square(unsigned long a) { return a * a; }

#5. 문자열 조작 (e)

  - 문자열화 연산자(#)는 이 연산자 다음에 나오는 것은 무엇이든 간에 겹따옴표 속에 넣어 문자열로 만든다.

#6. 문자열화 연산자 (f)

  - 문자열화 연산자는 그 연산자 다음에 나오는 어떤 글자들이라도 다음 공백 문자까지 겹따옴표로 둘러싸게 된다.

  1.        #define WRITERSTRING(x) count << #x
  2.        WRITERSTRING(This is a string);    =     count << "This is a string";

#7. 결합연산자 (g)

  - 결합연산자는 하나 이상의 용어를 합쳐서 새로운 단어로 만들어 내는 것이다.

  - 새 단어란 실제로 클래스 이름, 변수 이름, 배열에 대한 오프셋, 또는 어떤 것이든 나타날 수 있는 문자열로 사용할 수 있다.

  1.         #define fPrint(x) f ## x ## print
  2.         #define Listof(Type) class Type##List \
  3.          { \
  4.              public : \
  5.              Type##List(){} \
  6.              private : \
  7.              int itsLength; \
  8.          };

#8. 내장매크로 (h)

  - 많은 컴파일러들은 몇가지 유용한 매크로들을 내장하고 있다.

  - _DATE_ : 현재 날짜

     _TIME_ : 현재 시간

     _LINE_ : 소스코드 행 번호

     _FILE_ : 소스코드 파일 이름


  - 프로그램에서 사용하는 이름들과 겹칠 가능성을 줄이기 위해 두 개의 밑줄로 둘러 싸여 있다.

#9. assert() (i)

  - 매개 변수가 참으로 평가될 경우 참을 반환하고, 거짓으로 평가될 경우 몇 가지 종류의 동작을 한다.

  - 많은 컴파일러들이 assert()가 실패할 경우 프로그램을 강제로 종료한다. 그밖의 컴파일러들은 예외를 발생시킨다.

  - DEBUG가 정의되지 않을 경우 전처리기가 이 매크로를 무시한다. 수행성의 낭비나 실행 버전 프로그램의 크기의 증가가 없다.

  1.         #define DEBUG
  2.         #ifdef DEBUG
  3.              #define ASSERT(x)
  4.         #else
  5.              #define ASSERT(x) \
  6.                      if( !(x) ) \
  7.                      { \
  8.                            cout << "ERROR!! Assert " << #x << " falied\n"; \
  9.                            cout << "On line " << _LINE_ << "\n"; \
  10.                            cout << "in file" << _FILE_ << "\n"; \
  11.                       }
  12.          #endif

출처 : http://lonelysm.springnote.com/pages/4011761?print=1#h

이번에 컴퓨터를 업그레이드 하고 안드로이드 개발 환경을 다시 구축하는 도중, eclipse에 ADT 플러그인이 제대로 설치되지 않는 문제가 발생하였다. 그래서 eclipse 버젼도 바꿔보고, 수동으로 ADT 플러그인을 내려 받아서 설치도 해보았지만 제대로 진행이 되지 않았다.

정확한 error 메시지는 기억이 나지 않는다.
"The operation cannot be completed. See the details.: 였던 것 같다.

윈도우즈 임시 폴더를 임의로 다른 파티션으로 잡아 놓았었는데, 이걸 다시 C:\ 바꿔서 잡아주니 설치가 되는 것이였다.
현재 내 환경은 windows7 untimate k 64비트 sp1 버젼이다.

출처 : kldp

http://kldp.org/node/1725

 

 

참조 : http://www.joinc.co.kr/modules.php?name=News&file=article&sid=24

 

 

다음 과 같은 함수는 대몬화 하는 함수입니다.
int daemon_init(void)
{
pid_t pid;

if ( (pid = fork()) < 0)
return (-1);
else if (pid != 0)
exit(0); /* parent goes bye-bye */

/* child continues */
setsid(); /* become session leader */
chdir("."); /* change working directory */
umask(0); /* clear our file mode creation mask */

return (0);
}

함수가 이해가 안되는것이 아니고 왜 이렇게 하는지를 모르겠내요.
자세한 설명 부탁드릴게요.

 

 

 

 

답변 : xfmulder  님

 

일단 fork()해서 자신은 죽고 CHILD 를 남기는 이유는 init 의 자식이 되기 위해서이지요.
setsid() 함으로써 자신이 기존의 세션과 분리되면 제어 터미널을 잃습니다.
이때 getpgid() 하면 이전의 프로세스 그룹 으로부터도 독립되어 있게 됩니다.
참고로 프로세스와 관련된 id 는 네가지 입니다. pid, ppid, pgid(프로세스그룹), sid(세션ID) (getpid(), getppid() , getpgid() , getsid() 를 찾아보세요 )

세션id를 독립하면 자동으로 프로세스그룹ID(pgid) 도 sid 값으로 바뀝니다.
기존의 프로세스가 kill(0,SIGTERM); 하면 자신의 프로세스 그룹에 15번 시그널을 날리는데 이 데몬은 이미 프로세스그룹에서 독립했으므로 이 시그널 안받습니다. 물론 기존의 제어터미널에서도 독립했습니다.

chdir("/"); 하는건 현재디렉토리를 변경하는것. (자신이 로그를 기록할 적당한 디렉토리로 가도 됩니다. 상대PATH로 파일명 줄수 있음)

umask(0); umask 를 0 으로 했으므로 파일생성 모드 대로 생성됨.
(예를 들면 umask (022) 이면 파일을 rwxrwxrwx 로 생성해도 umask때문에
rwxr-xr-x 로 만들어 지게 됩니다)

[출처] daemon화 하는 펑션|작성자 김정은

물론 고수님들에겐 쉬운 문제지만 다음 구조체에서 char data[1]의 역할이 무엇인지 생각 해봅시다.

typedef struct tagWHATTHE {
int data1;
int data2;
char data[1];
} WHATTHE;

모르시는 분들은 최소 1분 정도 생각을 해봅시다.



그래도 잘 모르겠으면 약간의 힌트:

typedef struct tagWHATTHE {
int size;
int type;
char data[1];
} WHATTHE;



char data[1]의 역할은

난생 처음 이런 구조체를 보면 data[1] 변수가 도대체 어떤 의미인지 감을 잡기 힘들다. 왜 이런 변수가 쓰이는지는 직접 예제 코드를 보는 것이 가장 좋을 것 같다.

typedef struct tagHEADER {
int size;
int type;
char data[1];
} HEADER;

// int data_length, int* data;
HEADER* hd = (HEADER*)malloc(sizeof(HEADER) + data_length);
hd->size = sizeof(HEADER) + data_length;
hd->type = 0;
memcpy(hd->data, data, data_length);
fwrite(hd, 1, hd->size, file_handle);

한 마디로 char data[1]의 의미는 길이가 정해지지 않은 데이터를 담기 위한 일종의 더미 변수라고 보면 된다. 예에서도 있듯이 이런 코딩 테크닉은 어떤 데이터의 헤더를 표현할 때 많이 등장한다. 메모리 덩어리를 할당 받고 그것을 이 헤더 타입으로 캐스팅을 하면 앞 부분은 헤더가 놓이고 바로 뒤에 갖고 싶은 가변 길이 데이터를 쉽게 이을 수 있다. 윈도우 프로그래밍을 해보신 분이라면 아마 이런 것을 자주 봤을 것이다. 예를 들면:

typedef struct _RGNDATAHEADER {
DWORD dwSize;
DWORD iType;
DWORD nCount;
DWORD nRgnSize;
RECT rcBound;
} RGNDATAHEADER;

typedef struct _RGNDATA {
RGNDATAHEADER rdh;
char Buffer[1];
} RGNDATA;

RGN이라는 그래픽에서 그리는 영역을 지정하는 클리핑 객체를 담는 자료구조다. RGNDATA에 채워질 데이터가 몇 개나 올지 알 수 없으므로 이렇게 하였다. 또, 대표적인 비트맵 파일 관련 구조체도 빼놓을 수 없다.

typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;

배열 크기가 여기는 [1]인데 [0]으로 둬도 사실 문제 없다. 그리고 소켓 프로그래밍할 때 보게 되는 hostent에도 이제는 과거 호환성 때문에만 남았지만 크기가 0인 배열을 볼 수 있다. 그런데 보통 크기 0인 배열을 선언하면 컴파일러가 워닝을 띄운다. 그래서 C99 표준에는 flexible array member라고 해서 맨 마지막 구조체 변수의 선언이 char data[] 처럼 될 수 있도록 하기도 한다.

도대체 왜?

그렇다면 왜 이렇게 했을까? 보다 직관적으로 코드를 만든다면 아래처럼 쓸 수도 있다.

typedef struct tagHEADER {
int size;
int type;
char* data;
} HEADER;

HEADER* hd = (HEADER*)malloc(sizeof(HEADER));
hd->size = 1024;
hd->type = 0;
hd->data = (char*)malloc(hd.size);
...

그러나 이 접근은 단점이 있다. 위에서 예를 들었듯이 이 자료구조를 파일에 쓴다고 하면 헤더 부분 따로 그리고 data 영역을 따로 두 번에 걸쳐 파일 쓰기를 해야 한다. 결국 이 말은 이 자료구조에 접근하려면 헤더 한번, 실제 한번, 즉 두 번의 참조가 필요하다는 이야기다.

여기서 쪼잔하게 따지면 위 코드는 데이터 참조의 지역성(locality)이 줄어들어 캐시 미스를 한번 더 유발할 수 있는 단점도 있다. 요즘 프로세서들 캐시가 수 메가 바이트니 이 정도 괜찮다라는 생각을 함부로 하지 말자. 정말 성능이 중요한 프로그램은 이런 사소한 지역성 차이에서 오는 차이를 결코 무시할 수 없다. 비슷한 예로 “구조체의 배열(Array of Structure)” 이냐 “배열의 구조체(Structure of Array)”라는 문제도 있다 (우리말과 영어의 어순이 반대라 이거 이름이 참 헷갈린다). 간단한 예를 보면..

구조체의 배열(Array of Structure, AoS):

struct {
double x;
double y;
double z;
} vector[4];

배열의 구조체(Structure of Array, SoA):

struct {
double x[4];
double y[4];
double z[4];
} vector_set;

각각 상황에 따라 적절히 선택해서 골라야 한다. 사소해 보이지만 경우에 따라 큰 성능 차이가 나타날 수 있다.

AoS 같은 접근은 루프 한 순회에서 모든 원소들이 접근될 때 유리하다. vector[i]을 읽으면 일단 i번 째 x, y, z는 모두 캐시에 올라오기 때문이다. 반면 원소는 3개인데 루프에서 고작 x원소만 접근 된다면? 이 vector 배열이 매우 크다면 손실은 심각하다. 그럴 때는 SoA 구조가 바람직하다. 그 외에도 사소한 영향을 더 생각할 수 있지만 생각보다 글이 길어져서 이쯤에서 그만..

한줄요약: char data[1]; 같은 것이 보여도 쫄지 맙시다.

출 처 : http://minjang.egloos.com/2254472

sizeof 요넘이 자료형의 크기를 얻기위해 쓰이죠.

 

sizeof(int);

하면 int형이 몇바이트인지도 알 수 있고.

 

int i;

sizeof(i);

하면 변수 i가 몇바이트인지 알 수 있죠.

 

char arr[24];

sizeof(arr);

배열의 크기도 구할 수 있습니다.

 

---------------------------------------------------------

 

이러한 크기들은 어떻게 구하는 걸까요?

 

CPU가 계산해서 크기를 구하는게 아닌

컴파일러가 컴파일할때 크기를 인식해서 상수로 바꿉니다.

 

char arr[24];

printf("%d", sizeof(arr) );

여기서 sizeof(i)를 처리할 때...

컴파일러는 위의 배열을 선언한 부분을 참조합니다.

그리고 arr은 24바이트구나~~ 하면서

printf("%d", sizeof(arr) ); -> printf("%d", 24);

이렇게 바꿉니다.

 

----------------------------------------------------------

sizeof 는 컴파일러가 처리한다는 것을 알았으니

1개를 알려주면 10개를 안다는 분들은 감이 오실겁니다.

 

CPU가 32비트든, 64비트든, 운영체제가 32비트든 64비트든 간에

컴파일러가 32비트 컴파일러면 sizeof(int)는 모두 4로 처리된다는 겁니다.

 

32비트 CPU쓰고 32비트 운영체제를 쓴다 할지라도

16비트 컴파일러를 사용하면 sizeof(int)는 2가 됩니다.

 

-------------------------------------------------------------

 sizeof가 컴파일 될때 처리된다는 것을 알았으니

여기서 또 한가지를 알 수 있지요.

 

c언어로 표현하면

int *p;

p = malloc(16);

printf("%d", sizeof(p) );

일때, sizeof(p)는 어떻게 될까요?

정답은 16이 아닌 4 입니다.(32비트 컴파일러 기준)

 

p가 선언된 부분 int *p; 를 보고. 포인터는 4바이트니까 sizeof(p) -> 4

이렇게 한겁니다.

 

---------------------------------------------------------------------------

malloc(16)을 보면 16이라는 것을 알수 있는데, 컴파일러는 왜 4라고 처리하는가?

char arr[24];

printf("%d", sizeof(arr) );

배열 일때는 할당된 크기를 sizeof 값으로 처리했으면서.

 

 

malloc은 c언어 문법장치가 아닌, c언어 함수 입니다.

무슨말인가 하면, p = malloc(16);을 컴파일러 입장에서 보면.

"malloc 함수에 인자로 16을 주고, 리턴값을 p에 넣는다." 일 뿐이지 컴파일러에게 그 이상의 의미는 없습니다.

 

반면에 sizeof()는 함수가 아닌, c언어 문법장치 입니다.

그러므로 sizeof(p)가 "sizeof 함수에 p를 인자로 넣는다"가 아닌, "p의 바이트크기 상수값"을 의미하게 되는거지요.

 

배열일 때는, c언어 문법장치인 char arr[24]; 을 고려해서 sizof값을 정하는 것이고

포인터일 때는 c언어 문법장치인 int *p; 를 고려해서 sizof 값을 정하는 것입니다.

 

---------------------------------------------------

malloc 함수, 즉. 동적할당된 크기를 sizeof에 반영하지 않는 또다른 이유를 알아봅시다.

 

int *p;

int i;

scanf("%d", &i)

p = malloc(i);

printf("%d", sizeof(p) );

코드가 이러할때 sizeof(p)는 어떤 값을 가져야 할까요?

 

전에 말했듯이 sizeof는 c언어 문법장치이며, 함수도 아닙니다.

즉, 컴파일 될때 그 값이 결정되서 상수값으로 치환되어 컴파일 됩니다.

 

만약, malloc 으로 동적할당한 값을 sizeof 값으로 하려 한다면

컴파일 할때는 i의 값을 알수 없으므로 sizeof를 처리하는게 불가능 합니다.

 

이러한 이유도 있습니다.


출 처 : http://cafe.naver.com/haebop.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=5173

Cannot complete the install because one or more required items could not be found

I tried to install Android SDK and Eclipse Galileo on a fresh ubuntu 9.10 and found the error while installing ADT Plugin for Eclipse:

Cannot complete the install because one or more required items could not be found.
Software being installed: Android Development Tools 0.9.4.v200910220141-17704 (com.android.ide.eclipse.adt.feature.group 0.9.4.v200910220141-17704)
Missing requirement: Android Development Tools 0.9.4.v200910220141-17704 (com.android.ide.eclipse.adt.feature.group 0.9.4.v200910220141-17704) requires 'org.eclipse.wst.xml.core 0.0.0' but it could not be found


It's because there are some components missed in the setup, and the Galileo update site is not in the list of Available Software Sites.

To solve the problem:
Add "http://download.eclipse.org/releases/galileo" in the Available Software Sites.

제로 확장... unsigned 일 때
부호 확장... signed 일 때


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 부호 확장
#include 

int main()
{
	char A = 0x7A;
	int B = A;
	
	printf("B = %x\n", B);
	
	A = 0x8A;
	B = A;
	printf("B = %x\n", B);
	
	return 0;
}



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 제로 확장
#include <stdio.h>

int main()
{
	unsigned char A = 0x7A;
	unsigned int B = A;
	
	printf("B = %x\n", B);
	
	A = 0x8A;
	B = A;
	printf("B = %x\n", B);
    return 0;
}



1
2
3
4
5
6
7
8
9
10
11
// 확장
#include <stdio.h>

int main()
{
	char c = 0x8A;
	
	printf("%x\n", c);
	
	return 0;
}

printf 인자로 스택영역에 있는 c의 값을 넘겼다. 여기서 스택은 메모리에 있고 버스(32 bit)를 통과함으로 확장이 일어난다. c 변수 자체가 signed이기 때문에 부호 확장이 일어났음을 알 수 있다.


int a = 10;
Integer i = a;     // AutoBoxing...
 Stack 영역에 있던 값이 Heap 영역에 저장된다.

Integer i = new Integer(10);
int a = i;      // AutoUnboxing
 Heap 영역에 저장되어 있던 Integer 레퍼 객체의 값이 Stack 영역에 저장된다.


+ Recent posts