2016년 9월 1일 목요일

c 개념

삼항연산자, 매크로, const, 문자열 배열과 문자열 상수, 포인터 연산, 2차원 배열 동적 할당 및 해제, 소켓 통신


1. 삼항연산자
- 조건?식1:식2
  예: int y = (1>2)? 1:2;  // 조건이 true이면 1 false 이면 2

2. 매크로
- #define square(x) x*x
  square(3); 결과: 9. (3*3 이므로.)
  square(3+1); 결과: 7. (16이 아님. 3+1*3+1 이므로 3+3+1=7)
- #define square(x) (x)*(x)
  square(3+1); 결과: 16. ((3+1)*(3+1) 이므로.)
- #define border(x) (x)*3.14
  1/border(5); 결과: (1/5*3.14)
  만약 1/(5*3.14)가 되길 원한다면 border(x) ((x)*3.14) 로 작성해야 함.
- C언어의 매크로는 디버깅도 힘들고 복잡하므로 C++에서는 inline 함수를 사용.
  예: inline int abc(int x, int y) { return x+y; }

3. const
- const int val=30; 같이 초기화를 해야함.
  const in val; val=30; 으로 하면 초기화할때 val은 쓰레기 값이 들어가고, 컴파일 오류남.
- 포인터가 가리키는 데이터 상수화(상수지시포인터)
  const int * p = &n;
  *p = 20;  // 컴파일 에러
  p = &n1; // 에러없음.
- 포인터 자체를 상수화(상수 포인터)
  int * const p = &n;  // p가 가리키는 것을 상
  *p = 20;  // 에러없음.
  p = &n1; // 컴파일 에러
- 예
  int a=10; int b=20;
  const int *p = &a; //p는 정수의 자료형을 상수화 시킴. 다른 상수를 가리키는 것은 괜찮지만 자체 값은 못바꿈.
  int* const p = &a; // p 자체가 상수화됨. 따라서 p의 값을 변경하여 다른 것을 가리키게 할 수 없음. *p=20은 상관없음.

4. 문자열 배열과 문자열 상수
- 문자열 배열: char str1[5] = "abcd";
  str1[1] = 'z'; // 가능
- 문자열 상수: char *str2 = "abcd"
  str2[1] = 'z'; // 불가능

5. 배열
-  arr[i] = *(arr+i)

6. 포인터
- ptr[i] == *(ptr+i)
- ptr[i][j] == *(ptr[i]+j) ==(*(ptr+i))[j]
- ptr[0] == *ptr
  ptr[0][0] == **ptr
  ptr[0][1] == (*ptr)[1] != *ptr[1]
- int *p;
  p++;  // 4byte 증가
  p+=4;  // 16byte 증가
- int *p;
  p--;  // 4byte 감소
  p –= 2; // 8byte 감소
- 단항연산자
  *++ptr == *(++ptr)
  ++*ptr == ++(*ptr)
  *&ptr == *(&ptr)
  *ptr++ == *(ptr++)
  &arr[1] == &(arr[1])

7. 2차원 배열 동적 할당 및 해제
- int **arr;
  arr = (int *) malloc ( sizeof(int) * 5 );
  for(int i=0; i<3; i++){
    arr[i] = (int*) malloc ( sizeof(int) * 3);
  }
- for(i=0; i<3; i++)
    free(arr[i]);
  free(arr);

8. 소켓 통신 - 서버
- socket() 함수
  int server_socket;
  server_socket = socket( PF_INET, SOCK_STREAM, 0);
  if (-1 == server_socket) {
    printf( "server socket 생성 실패");
    exit( 1) ;
  }

- bind() 함수
  server socket 에 필요한 정보를 할당하고 커널에 등록. 만들어진 server_socket 은 단지 socket 디스크립터일 뿐.
  socket에 주소를 할당하고 port 번호를 할당해서 커널에 등록해야 함.
  socket에 주소와 port 를 할당하기 위해 sockaddr_in 구조체를 이용함.

  struct sockaddr_in server_addr;
  memset( &server_addr, 0, sizeof( server_addr);
  server_addr.sin_family = AF_INET; // IPv4 인터넷 프로토롤
  server_addr.sin_port = htons( 4000); // 사용할 port 번호는 4000
  server_addr.sin_addr.s_addr = htonl( INADDR_ANY); // 32bit IPV4 주소

  if( -1 == bind( server_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
  {
    printf( "bind() 실행 에러\n");
    exit( 1);
  }
  htonl( INADDR_ANY) 는 주소를 지정해 주는 것으로 inet_addr( "내 시스템의 IP ")로도 지정할 수 있음.
  그러나 프로그램이 실행되는 시스템 마다 IP 가 다를 것이므로 주소 지정을 고정 IP로 하지 않고 htonl( INADDR_ANY) 를 사용하는 것이 편리함.


- listen() 함수
  클라이언트 접속 요청을 확인하는 함수.
  if( -1 == listen( server_socket, 5))
  {
    printf( "대기상태 모드 설정 실패\n");
    exit( 1);
  }

- accept() 함수
  클라이언트 접속 요청 허락 함수.
   accept()로 접속 요청을 허락하게 되면 클라이언트와 통신을 하기 위해서 커널이 자동으로 소켓을 생성함.
  client socket 정보를 구하기 위해 변수를 선언하고, client 주소 크기를 대입함.

  int     client_addr_size;
  client_addr_size = sizeof( client_addr);
  accept()를 호출 후에 에러가 없으면 커널이 생성한 client socket 을 반환해 줍니다.
  client_socket = accept( server_socket, (struct sockaddr*)&client_addr, &client_addr_size);
  if ( -1 == client_socket)
  {
     printf( "클라이언트 연결 수락 실패\n");
     exit( 1);
  }

- read(), write() 함수
  자료를 송수신 함

  read() 함수를 이용하여 클라이언트로부터 전송되어 오는 자료를 읽어 들임.
  read ( client_socket, buff_rcv, BUFF_SIZE);

  write() 를 이용하여 클라이언트로 자료를 송신합니다.
  buff_snd: 전송하는 메시지, strlen(buff_snd)+1: 전송하는 메시지 길이
  write( client_socket, buff_snd, strlen( buff_snd)+1); // +1: NULL까지 포함해서 전송

- close() 함수
  client socket 을 소멸 시켜 데이터 통신을 종료 함.
  close( client_socket);

9. 소켓 통신 - 서버
- socket() 함수
  소켓을 생성.
  int     client_socket;
  client_socket = socket( PF_INET, SOCK_STREAM, 0);
  if( -1 == client_socket)
  {
     printf( "socket 생성 실패\n");
     exit( 1);
  }

- connect() 함수
  주소 정보에 서버의 주소와 포트번호를 지정하고 서버와의 연결을 시도함.

  struct sockaddr_in    server_addr;
  memset( &server_addr, 0, sizeof( server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons( 4000);
  server_addr.sin_addr.s_addr= inet_addr( "127.0.0.1");  // 서버의 주소
  if( -1 == connect( client_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
  {
     printf( "접속 실패\n");
     exit( 1);
  }

- write(), read() 함수
 접속에 성공하면 데이터를 전송함.
  write( client_socket, argv[1], strlen( argv[1])+1); // +1: NULL까지 포함해서 전송

  자료를 수신하고 화면에 출력함.
  read ( client_socket, buff, BUFF_SIZE);
  printf( "%s\n", buff);

- close() 함수
  socket 을 소멸하여 통신 작업을 완료함.

  close( client_socket);

* 소켓 통신 출처
- http://forum.falinux.com/zbxe/index.php?document_srl=429387&mid=C_LIB

댓글 없음:

댓글 쓰기