사용하지 않는 줄을 주석 처리 한 후 Switch-case가 컴파일되지 않습니다.


82

내 코드는 다음과 같습니다.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main (void) {

  struct addrinfo hints; 
  memset (&hints, 0, sizeof hints);

  hints.ai_family = AF_UNSPEC; 
  hints.ai_socktype = SOCK_DGRAM;  
  hints.ai_flags = AI_CANONNAME;   

  struct addrinfo *res;

  getaddrinfo ("example.com", "http", &hints, &res);
  printf ("Host: %s\n", "example.com");

  void *ptr;

  while (res != NULL) {
    printf("AI Family for current addrinfo: %i\n", res->ai_family);
    switch (res->ai_family) {
      case AF_INET:
        ptr = (struct sockaddr_in *) res->ai_addr;
        struct sockaddr_in *sockAddrIn = (struct sockaddr_in *) res->ai_addr;
        break;
    }
    res = res->ai_next;
  }
  return 0;
}

잘 컴파일됩니다.

그러나이 줄을 주석 처리하면 :

//ptr = (struct sockaddr_in *) res->ai_addr;

나는 얻을 것이다 :

$ gcc ex4.c
ex4.c:30:9: error: expected expression
        struct sockaddr_in *sockAddrIn = (struct sockaddr_in *) res->ai_addr;
        ^
1 error generated.

내가 무엇을 놓치고 있습니까?


이 질문의 제목을 수정해야할까요? 더 많은 경험이있는 사람이 동의한다면 이것을 할 수 있습니까?
Koray Tugay 2015 년

원하는 경우 직접 편집 할 수 있어야합니다. 하지만 제목이 더 좋을 수 있다는 데 동의합니다.
QuestionC

@KorayTugay, 나는 그것을 실행했다.
Paul Draper

1
내부에 변수 선언이있는 경우 case(상위 답변에서 제안한대로 중괄호를 묶지 않음) 변수 이름이 나중에 표시 case되지만 초기화되지 않은 경우 (드롭 다운하지 않는 한 ) 잘못된 생각 입니다.
MM

답변:


111

switch 문의 각 케이스는 기술적으로 말하면 레이블입니다. 일부 모호하고 오래된 이유로 인해 레이블 뒤의 첫 번째 줄로 변수 선언을 할 수 없습니다. 과제를 주석 처리하여

ptr = (struct sockaddr_in *) res->ai_addr;

라인

struct sockaddr_in *sockAddrIn = (struct sockaddr_in *) res->ai_addr;

AF_INET:내가 말했듯이 C에서 불법 인 레이블 다음의 첫 번째 줄 이됩니다.

해결책은 모든 case 문을 다음과 같이 중괄호로 묶는 것입니다.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main (void) {

  struct addrinfo hints; 
  memset (&hints, 0, sizeof hints);

  hints.ai_family = AF_UNSPEC; 
  hints.ai_socktype = SOCK_DGRAM;  
  hints.ai_flags = AI_CANONNAME;   

  struct addrinfo *res;

  getaddrinfo ("example.com", "http", &hints, &res);
  printf ("Host: %s\n", "example.com");

  void *ptr;

  while (res != NULL) {
    printf("AI Family for current addrinfo: %i\n", res->ai_family);
    switch (res->ai_family) {
      case AF_INET:
      {
        ptr = (struct sockaddr_in *) res->ai_addr;
        struct sockaddr_in *sockAddrIn = (struct sockaddr_in *) res->ai_addr;
        break;
      }
    }
    res = res->ai_next;
  }
  return 0;
}

어쨌든, 이것이 더 나은 코딩 연습이라고 생각합니다.


22
좋은. Nitpicking "각 케이스는 ... 레이블이 붙은 진술입니다." 그리고 그것이 그 이유입니다 : 진술은 라벨이 붙을 수 있지만 선언은 할 수 없습니다.
undur_gongor

4
@KorayTugay 때때로 컴파일러 메시지는 우리가 원하는대로 유익하지 않습니다 .... 때로는 너무 유익합니다 (기침 기침 C ++ stl 기침 기침).
John M

5
@BlueMoon 당신이 맞아요. C ++ stl 오류 메시지를 단순화하는 도구를 구입할 수 있으면 정보 밀도가 엄청나게 낮다는 것을 알 수 있습니다!
John M

3
아니면 그냥 스위치 블록 전에 선언을 이동
파벨 Gatnar

3
@immibis : C ++에서 선언은 명령문이므로 C ++에서 제한없이 선언에 레이블을 지정할 수 있습니다. C에서 선언은 명령문이 아니므로 레이블을 지정할 수 없습니다. 다음은 C와 C ++의 차이점을 보여주는 예입니다. stackoverflow.com/a/19830820/187690
AnT

15

허용 된 답변을 보완하기 위해 케이스 레이블 앞에 변수를 선언 할 수 있습니다.

switch(a) {
    int b; //can't initialize variable here
    case 0:
    ...
}

또는 빈 문장을 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.