ISO C90 cấm khai báo hỗn hợp và mã trong C


82

Tôi đã khai báo một biến theo cách này:

int i = 0;

Tôi nhận được cảnh báo:

ISO C90 cấm các khai báo và mã hỗn hợp

Làm thế nào tôi có thể sửa chữa nó?


2
Nó có vẻ giống như GCC -pedantichoặc -std=c89, trong trường hợp đó, bạn có thể biên dịch -std=gnu99nếu muốn.
Dietrich Epp

3
Nếu bạn đang sử dụng gcc, bạn có thể chỉ định sử dụng C99 cho phép khai báo hỗn hợp và mã (cờ -std=c99).
hmjd

11
Một lựa chọn sẽ là ngừng biên dịch theo một tiêu chuẩn đã 22 tuổi mà ngay cả tiêu chuẩn đã được thay thế.
Stephen Canon

4
@StephenCanon, hãy nói với Microsoft điều đó. :)
hmjd

2
@hmjd: Microsoft không quan tâm đến việc vận chuyển trình biên dịch C; điều đó có thể sẽ không thay đổi. May mắn thay, có một số trình biên dịch hoàn toàn tốt nhắm mục tiêu nền tảng do các nhà cung cấp khác cung cấp.
Stephen Canon

Câu trả lời:


124

Tôi nghĩ bạn nên chuyển phần khai báo biến lên đầu khối. I E

{
    foo();
    int i = 0;
    bar();
}

đến

{
    int i = 0;
    foo();
    bar();
}

5
... hoặc mở một bối cảnh mới:{foo(); {int i=0; bar();}}
alk

3
@alk s / context / block Đó là những gì nó được gọi trong Tiêu chuẩn C.
Jens

@Johan Kotlinski Nhưng tại sao điều này lại quan trọng?
Ocean800

1
@ ocean800 Đặc điểm kỹ thuật C90 cho biết rằng bạn không thể có các khai báo sau khi không khai báo trong cùng một khối.
MM

37

Cho đến trước tiêu chuẩn C99, tất cả các khai báo phải đứng trước bất kỳ câu lệnh nào trong một khối:

void foo()
{
  int i, j;
  double k;
  char *c;

  // code

  if (c)
  {
    int m, n;

    // more code
  }
  // etc.
}

C99 được phép trộn các khai báo và câu lệnh (như C ++). Nhiều trình biên dịch vẫn mặc định C89, và một số trình biên dịch (chẳng hạn như Microsoft) không hỗ trợ C99 ở tất cả .

Vì vậy, bạn sẽ cần phải làm như sau:

  1. Xác định xem trình biên dịch của bạn có hỗ trợ C99 trở lên hay không; nếu có, hãy cấu hình nó để nó biên dịch C99 thay vì C89;

  2. Nếu trình biên dịch của bạn không hỗ trợ C99 hay muộn, bạn sẽ hoặc là cần phải tìm một trình biên dịch khác nhau mà không hỗ trợ nó, hoặc viết lại mã của bạn để tất cả các tờ khai đến trước bất kỳ báo cáo trong khối.


11

Chỉ cần sử dụng một trình biên dịch (hoặc cung cấp cho nó các đối số mà nó cần) để nó biên dịch cho phiên bản mới hơn của tiêu chuẩn C, C99 hoặc C11. Ví dụ: đối với dòng trình biên dịch GCC -std=c99.


6
Câu trả lời này là không đầy đủ nhất. Nó khắc phục được sự cố nhưng không giải thích nguyên nhân gây ra sự cố. Câu trả lời này loại trừ các trường hợp không thể sử dụng trình biên dịch mới hơn (một số lý do có thể xảy ra ...) hoặc xây dựng môi trường mà việc chuyển đổi các tùy chọn sang trình biên dịch như thế này là không thể. Một cuộc bỏ phiếu xuống vì tôi không thể đồng ý rằng đây là câu trả lời "thực sự".
Andrew Falanga

1
Trong một số trường hợp -std=gnu89được sử dụng khi biên dịch mô-đun nhân linux.
cbix

4

Đảm bảo rằng biến nằm ở phần trên cùng của khối và trong trường hợp bạn biên dịch nó với -ansi-pedantic, hãy đảm bảo rằng biến đó trông giống như sau:

function() {
    int i;
    i = 0;

    someCode();
}

Bạn vẫn có thể khởi tạo biến, chỉ là bạn không thể đặt mã trước khi khai báo.
SS Anne

2

Để chẩn đoán điều gì thực sự gây ra lỗi, trước tiên tôi sẽ cố gắng loại bỏ = 0

  • Nếu lỗi xảy ra, thì rất có thể phần khai báo đi sau mã.

  • Nếu không có lỗi, thì nó có thể liên quan đến cờ biên dịch / thực thi tiêu chuẩn C HOẶC ... thứ gì đó khác.

Trong mọi trường hợp, hãy khai báo biến ở đầu phạm vi hiện tại. Sau đó, bạn có thể khởi tạo nó một cách riêng biệt. Thật vậy, nếu biến này xứng đáng với phạm vi riêng của nó - hãy phân tách định nghĩa của nó trong {}.

Nếu OP có thể làm rõ bối cảnh, thì một phản ứng có định hướng hơn sẽ theo sau.


1

-Wdeclaration-after-statement ví dụ có thể tái tạo tối thiểu

C chính

#!/usr/bin/env bash

set -eux

cat << EOF > main.c
#include <stdio.h>

int main(void) {
    puts("hello");
    int a = 1;
    printf("%d\n", a);
    return 0;
}
EOF

Đưa ra cảnh báo:

gcc -std=c89 -Wdeclaration-after-statement -Werror main.c
gcc -std=c99 -Wdeclaration-after-statement -Werror main.c
gcc -std=c89 -pedantic -Werror main.c

Đừng đưa ra cảnh báo:

gcc -std=c89 -pedantic -Wno-declaration-after-statement -Werror main.c
gcc -std=c89 -Wno-declaration-after-statement -Werror main.c
gcc -std=c99 -pedantic -Werror main.c
gcc -std=c89 -Wall -Wextra -Werror main.c
# https://stackoverflow.com/questions/14737104/what-is-the-default-c-mode-for-the-current-gcc-especially-on-ubuntu/53063656#53063656
gcc -pedantic -Werror main.c

Cảnh báo:

main.c: In function ‘main’:
main.c:5:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
     int a = 1;
     ^~~

Đã thử nghiệm trên Ubuntu 16.04, GCC 6.4.0.

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.