Switch-case sẽ không biên dịch sau khi nhận xét ra một dòng không sử dụng


82

Đây là mã của tôi:

#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;
}

mà biên dịch tốt.

Tuy nhiên, khi tôi nhận xét dòng này:

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

Tôi sẽ nhận:

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

Tôi đang thiếu gì?


Có lẽ nên chỉnh sửa tiêu đề của câu hỏi này? Ai đó có kinh nghiệm hơn có thể làm điều này nếu đồng ý như vậy không?
Koray Tugay

Bạn có thể tự chỉnh sửa nếu muốn. Nhưng tôi đồng ý, tiêu đề có thể tốt hơn.
Câu

@KorayTugay, tôi đã chạy thử.
Paul Draper

1
Có một khai báo biến bên trong a case(không có dấu ngoặc nhọn xung quanh như câu trả lời trên cùng đề xuất) là một ý tưởng tồi vì sau đó tên của biến sẽ hiển thị trong casecác s sau nhưng nó sẽ không được khởi tạo (trừ khi bạn bỏ xuống).
MM

Câu trả lời:


111

Về mặt kỹ thuật, mỗi trường hợp trong câu lệnh switch là một nhãn. Vì một số lý do khó hiểu và cũ , bạn không được phép khai báo biến ở dòng đầu tiên sau nhãn. Bằng cách nhận xét bài tập

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

dòng

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

trở thành dòng đầu tiên sau nhãn AF_INET: , như tôi đã nói, là bất hợp pháp trong C.

Giải pháp là đặt tất cả các câu lệnh trường hợp của bạn trong dấu ngoặc nhọn như sau:

#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;
}

Dù sao, tôi nghĩ rằng đây là thực hành mã hóa tốt hơn.


22
Đẹp. Nitpicking "Mỗi trường hợp ... là ... một tuyên bố được gắn nhãn". Và đó là lý do: các câu lệnh có thể được gắn nhãn nhưng không phải là phần khai báo.
undur_gongor

4
@KorayTugay Đôi khi các thông báo của trình biên dịch không có nhiều thông tin như chúng ta muốn .... đôi khi chúng quá nhiều thông tin ( khụ khụ C ++, khụ khụ khụ ).
John M

5
@BlueMoon Bạn nói đúng. Khi bạn có thể mua một công cụ để đơn giản hóa thông báo lỗi stl trong C ++, bạn biết rằng mật độ thông tin là cực kỳ thấp!
John M

3
hoặc chỉ di chuyển tờ khai trước khi khối switch
Pavel Gatnar

3
@immibis: Trong C ++ khai báo là các câu lệnh, đó là lý do tại sao trong C ++ bạn có thể gắn nhãn các khai báo mà không có bất kỳ hạn chế nào. Trong C khai báo không phải là câu lệnh, đó là lý do tại sao bạn không thể gắn nhãn chúng. Dưới đây là một ví dụ minh họa sự khác biệt này giữa C và C ++: stackoverflow.com/a/19830820/187690
AnT

15

Như một phần bổ sung cho câu trả lời được chấp nhận, bạn có thể khai báo các biến của mình trước nhãn trường hợp.

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

Hoặc chỉ sử dụng một câu lệnh trống.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.