Компиляция на терминале выдает предупреждение об указателе и странные символы

Я пытаюсь скомпилировать и запустить простую C-программу из моего терминала. Это мой код:

#include <stdio.h>
//integers that are 3n, 3n + 1, and 3n + 2

int main(){
  int n,i,a,b,c;
  scanf("%d", &n);
  for (;n>0;n--) {
    scanf("%d", &i);
    if(n%3==0){a+=1;}
    if(n%3==1){b+=1;}
    if(n%3==2){c+=1;}
  }
  printf("%d %d %d", &a,&b,&c);
  return 0;
}

После его компиляции он генерирует это предупреждение:

warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]

Я не понимаю, почему он генерирует это предупреждение, потому что я не назначаю переменные указателя. Почему это генерирует это?

Кроме того, после компиляции в пару раз больше мой c-файл превращается в символы. Я не понимаю, почему это происходит. Имя моего файла - 73.c, и вот как я его компилирую в Terminal:

gcc 73.c -o 73.c

После этого мой файл преобразуется во что-то вроде этого (строки и строки этого):

œ˙Ì˛����Ä��������Ö� ��������H���__PAGEZERO��������������������������������������������������������(��__TEXT����������������������������������������������������__text����������__TEXT����������0�����˝�������0���������������Ä������������__stubs���������__TEXT����������.������������.��������������Ä�����������__stub_helper���__TEXT����������<�����$�������<���������������Ä������������__cstring�������__TEXT����������`������������`�����������������������������__unwind_info���__TEXT����������l�����H�������l������������������������������__eh_frame������__TEXT����������∏�����@�������∏��������������������������������Ë���__DATA��������������������������������������������������__nl_symbol_ptr�__DATA���������������������������������������������������__la_symbol_ptr�__DATA����������������������������������������������������H���__LINKEDIT������� ������������� ������`��������������������"��Ä0���� ����� �������������  �� ���@ ��0���������∏ ����� !��@���

Я действительно понятия не имею, что происходит. Я занимаюсь этим уже давно, я знаю, что это не должно быть так сложно, но я действительно не знаю, в чем дело. Кто-нибудь имеет представление о том, что может происходить?

2 ответа

Решение

Есть две основные вещи, которые здесь не так:

  1. Вы пытаетесь напечатать адрес переменных a, b а также c,
  2. Вы вызываете неопределенное поведение, но не инициализируете свои счетчики равными 0.

Вы хотите напечатать целые числа, поэтому измените это:

printf("%d %d %d", &a,&b,&c);

к этому:

printf("%d %d %d", a, b, c);

Я также добавил несколько пробелов, но это просто для того, чтобы украсить код, сделать его более читабельным, это не повлияет на выполнение.

Вы не хотите печатать адреса! Вот почему вы получаете предупреждение. Подробнее читайте здесь: В чем разница между операторами * и & в программировании на c?


Как упомянул achelper, вы не компилируете свою программу, как следует (но это не проблема кода), но это то, к чему вы должны привыкнуть. Я покажу, что я сделал, чтобы скомпилировать мне программу (я также люблю использовать -Wall флаг, который включает все предупреждения):

C02QT2UBFVH6-lm:~ gsamaras$ nano main.c
C02QT2UBFVH6-lm:~ gsamaras$ gcc main.c -Wall -o main
main.c:13:22: warning: format specifies type 'int' but the argument has type
      'int *' [-Wformat]
  printf("%d %d %d", &a,&b,&c);
          ~~         ^~
main.c:13:25: warning: format specifies type 'int' but the argument has type
      'int *' [-Wformat]
  printf("%d %d %d", &a,&b,&c);
             ~~         ^~
main.c:13:28: warning: format specifies type 'int' but the argument has type
      'int *' [-Wformat]
  printf("%d %d %d", &a,&b,&c);
                ~~         ^~
main.c:11:16: warning: variable 'c' is uninitialized when used here
      [-Wuninitialized]
    if(n%3==2){c+=1;}
               ^
main.c:5:16: note: initialize the variable 'c' to silence this warning
  int n,i,a,b,c;
               ^
                = 0
main.c:10:16: warning: variable 'b' is uninitialized when used here
      [-Wuninitialized]
    if(n%3==1){b+=1;}
               ^
main.c:5:14: note: initialize the variable 'b' to silence this warning
  int n,i,a,b,c;
             ^
              = 0
main.c:9:16: warning: variable 'a' is uninitialized when used here
      [-Wuninitialized]
    if(n%3==0){a+=1;}
               ^
main.c:5:12: note: initialize the variable 'a' to silence this warning
  int n,i,a,b,c;
           ^
            = 0
6 warnings generated.
C02QT2UBFVH6-lm:~ gsamaras$ ./main
2
1
2
1461300256 1461300252 1461300248C02QT2UBFVH6-lm:~ gsamaras$ 

В общем, если вы сомневаетесь, воспринимайте предупреждения как ошибки, поэтому давайте отладим этот код вместе, это будет весело. Pro-tip: Начните с первого предупреждения и устраните его. После этого, следующие предупреждения могут быть связаны, и, таким образом, они не будут прочитаны!

После применения моего предложения все предупреждения, связанные с тем, что вы описали в своем вопросе, исчезли. Оставляются только неинициализированные переменные.

Это просто, просто инициализируйте ваши переменные к некоторому начальному значению, например -1, если это, конечно, имеет смысл.

В вашем случае, тем не менее, вы используете a, b а также c как счетчики! Поэтому вы должны инициализировать их равными 0, в противном случае вы начинаете добавлять свои значения к значениям мусора, и это вызывает неопределенное поведение!

Так что измени это:

int n,i,a,b,c;

к этому:

int n, i, a = 0, b = 0, c = 0;

Без инициализации счетчиков я получаю на своей машине сейчас

C02QT2UBFVH6-lm:~ gsamaras$ ./main
2
1
2
1505029184 1 1C02QT2UBFVH6-lm:~ gsamaras$

Ты видишь это printf() дает мне немного мусора, в то время как после инициализации моих счетчиков до 0, я получил:

C02QT2UBFVH6-lm:~ gsamaras$ ./main
2
1
2
0 1 1C02QT2UBFVH6-lm:~ gsamaras$ 

Упомянутые gsamaras пункты верны, вы должны использовать:

 printf("%d %d %d", a, b, c);

Синтаксис, который вы использовали, используется в

  • scanf (передавайте адрес переменной, где данные должны быть заполнены.)

  • Также инициализируйте переменные при определении.

Относительно компиляции: имя -o указывает выходной файл, сгенерированный после компиляции, таким образом, он перезаписывает ваш исходный код (т. Е. 73.c). Если вы опустите -o, выходной файл по умолчанию будет сгенерирован как a.out. Поэтому для компиляции вы можете использовать следующее и запустить программу как./a.out:

gcc 73.c

man gcc цитаты:

-o файл Поместить вывод в файл. Это относится к любому виду вывода, будь то исполняемый файл, объектный файл, файл ассемблера или предварительно обработанный код C.

Если -o не указан, по умолчанию помещается исполняемый файл в a.out, объектный файл для source.suffix в source.o, его файл ассемблера в source.s, предварительно скомпилированный заголовочный файл в source.suffix.gch и все предварительно обработанные C-источники на стандартном выходе.

Другие вопросы по тегам