Язык программирования C, массив, указатель - PullRequest
0 голосов
/ 02 октября 2010
int main()
{
    int j=97;
    char arr[4]="Abc";
    printf(arr,j);
    getch();
    return 0;
}

этот код дает мне ошибку переполнения стека, почему?Но если вместо printf(arr,j) мы используем printf(arr), то печатается Abc.скажите, пожалуйста, как работает printf, значит, 1-й аргумент имеет тип const char*, так как компилятор обрабатывает arr.извиняюсь!Приведенный выше код прав, это не дает никакой ошибки, я пишу это по ошибке.но приведенный ниже код дает ошибку переполнения стека.

#include <stdio.h>
int main()
    {
       int i, a[i];
       getch();
       return 0;
    }

, поскольку в качестве переменной я беру любое значение мусора, так что это будет размер массива, так почему этот код дает эту ошибку, когда я использую DEV C ++ и если я использую TURBOC ++ 3.0 затем ошибка: требуется отображение константного выражения.если размер массива не может быть переменным, тогда, когда мы берем размер массива через пользователя input.no, ошибка не отображается.но почему в этом случае.

Ответы [ 5 ]

3 голосов
/ 02 октября 2010

Я вижу, что теперь ОП изменил описание поведения на нечто совершенно иное, поэтому мое объяснение больше не относится к его коду.Тем не менее, замечания, которые я высказал в отношении функций с переменными числами, остаются в силе.

Этот код приводит к аннулированию стека (или что-то подобное), поскольку вы не смогли объявить функцию printf.printf - это так называемая переменная функция, она принимает переменное число аргументов.В языке Си это [почти] всегда было обязательным для объявления функций с переменными числами перед их вызовом.Практическая причина этого требования заключается в том, что для функций с переменным числом аргументов (и часто это будет необходимо) требуется особый подход к передаче аргументов.Его часто называют соглашением о вызовах .Если вы забудете объявить функцию с переменным числом перед вызовом, компилятор до C99 предположит, что это обычная невариационная функция, и вызовет ее как обычную функцию.Т.е. он будет использовать неправильное соглашение о вызовах, что, в свою очередь, приведет к аннулированию стека.Все зависит от реализации: некоторые из них могут даже работать "нормально", некоторые будут зависать.Но в любом случае у вас абсолютно есть для объявления функций с переменным числом перед их вызовом.

В этом случае вы должны включить <stdio.h> перед вызовом printf.Заголовочный файл <stdio.h> является стандартным заголовком, который содержит объявление printf.Вы забыли это сделать;отсюда и ошибка (скорее всего).Невозможно быть на 100% уверенным, поскольку это зависит от реализации.

В противном случае ваш код верен.Код странный, поскольку вы передаете j в printf без указания спецификатора формата, но это не ошибка - printf просто игнорирует дополнительные переменные аргументы.Ваш код должен печатать Abc в любом случае.Добавьте #include <stdio.h> в начале вашего кода, и он должен работать нормально, если он делает то, что вы хотели.

Опять же, этот код

#include <stdio.h>

int main()
{
    int j=97;
    char arr[4]="Abc";
    printf(arr,j);
    return 0;
}

странный,но совершенно правильная C-программа с идеально определенным выводом (хотя было бы неплохо добавить \n в конце вывода).

3 голосов
/ 02 октября 2010

скажите, пожалуйста, как работает printf

Прежде всего, передает только не предоставленные пользователем или проверенные строки в первый аргумент printf()!

printf() принимает переменное число аргументов после обязательного const char* аргумента (потому что printf() - это то, что называется variadic function ).Первый аргумент const char* - это то, где вы передаете строку формата , чтобы printf() знал, как отобразить остальные ваши аргументы.

Если массив символов arr содержит user-введенные значения, то это может вызвать ошибку по умолчанию, если строка содержит эти заполнители форматирования, поэтому строка формата всегда должна быть жестко закодированной константной (или проверенной) строкой.Ваш пример кода достаточно прост, чтобы увидеть, что он действительно является константой, но все же хорошей практикой является привыкание к printf("%s", arr) для отображения строк вместо передачи их непосредственно первому аргументу (если, конечно, вы не обязаны это делать).

При этом для форматирования вывода используются заполнители форматирования (те, которые начинаются с %).Если вы хотите отобразить:

Abc 97

Тогда ваш звонок на printf() должен быть:

printf("%s %d", arr, j);

%s говоритprintf() что второй аргумент должен интерпретироваться как указатель на строку с нулевым символом в конце.%d сообщает printf(), что третий аргумент следует интерпретировать как десятичное число со знаком.

этот код вызывает ошибку переполнения стека, почему?

См. Ответ AndreyT.

1 голос
/ 03 октября 2010

В вашей строке int i, a[i]; в исправленном образце неработающего кода a - это массив переменной длины i элементов, но i неинициализирован.Таким образом, ваша программа имеет неопределенное поведение.

0 голосов
/ 02 октября 2010

Вы видите, что строки на языке C обрабатываются как char*, а функция printf может печатать строку напрямую. Для печати строк с использованием этой функции вы должны использовать такой код:

printf("%s", arr);

% s сообщает функции, что первая переменная будет char*.

Если вы хотите напечатать как arr, так и j, вы должны сначала определить формат:

printf("%s%d", arr, j);

% d сообщает функции, что вторая переменная будет int

0 голосов
/ 02 октября 2010

Я подозреваю, что проблема printf () - это красная сельдь, поскольку с "Abc" с нулевым символом в конце будут игнорироваться другие аргументы.ваша программа?Если нет, вы можете быть уверены, что ошибка не в getch () ?
Я не могу дублировать вашу проблему, но затем я закомментировал getch () для простоты.

Кстати, почему вы не использовали fgetc () или getchar () ?Вы собираетесь использовать curses в более крупной программе?

===== Добавлено после редактирования =====

Хорошоне красная сельдь, просто ошибка ОП.

C ++ позволяет выделить массив с размером, указанным переменной;по сути, вы сделали это со случайным (мусорным) размером и переполнили стек, как вы поняли.Когда вы компилируете с C ++, вы, как правило, больше не компилируете C, и правила меняются (в зависимости от конкретного компилятора).

Тем не менее, я не понимаю вашего вопроса - вам нужно быть намного более ясным с« когда мы берем размер массива через пользовательский ввод » ...

...