Member 13188016 Ответов: 3

Почему переменная указателя со звездочкой и без звездочки ведет себя по-разному в функции printf


Я новичок в программировании, есть какая-то часть, которая заставила меня запутаться при изучении указателя.


int main()
{
    char string[]="hello";

    char *my_pointer=string;

    printf("first character is %c", *my_pointer);
    return 0;
}

вывод: первый символ-h

код 2:

int main()
{    
    char array_of_words[]="one\0two\0three";

    char *my_pointer=array_of_words;

    printf("%s \n",my_pointer);

    return 0;
}

выход : один

Что я уже пробовал:

вопросы:

Я запутался здесь, часть функции printf в первом коде, использующая символ звездочки, означает указывать на то, что находится внутри указателя (my_pointer), который является адресом переменной строки, ссылающейся на строку указателя для массива, указывающего адрес памяти первого слова в массиве "hello". верно ли мое понимание?

а также когда я меняю %c в printf ("первый символ - %c", *my_pointer); на %s, программа падает. я хочу знать, почему я не могу использовать %s и что отличается, если я не использую звездочку в my_pointer в printf("первый символ - %c", my_pointer);

В то время как во втором коде *my_pointer=array_of_words скопируйте адрес первого содержимого array_of_the_words, который является 'o'? И char *my_pointer=array_of_the_words означает, что мы хотим *my_pointer имеет тот же адрес, array_of_the_words которые относятся к это'о'(?) если my_pointer в printf("%з\п",my_pointer) относится к памяти в адрес *my_pointer то почему бы не произвести "один" и не выпускать 'о' ??

На самом деле он копирует первый строковый адрес, но содержит все слова?
Но почему Во-первых использовать код *my_pointer в printf и второй код my_pointer в printf?
Я знаю, что *my_pointer относится к значению, а my_pointer - к адресу, но почему вывод отличается

3 Ответов

Рейтинг:
5

Richard MacCutchan

Корпус 1:

printf("first character is %c", *my_pointer);

Вы говорите printf для вывода одного символа (%c) таким образом, параметр после строки формата должен быть одним символом. Так как символ находится внутри массива, на который указывает my_pointer он должен быть извлечен из массива, и способ сделать это - использовать оператор разыменования (*), который вернет единственный символ из указанного местоположения.

Случай 2:
printf("%s \n",my_pointer);

В данном случае вы рассказываете printf для вывода последовательности символов (%s) поэтому вы должны передать адрес этой последовательности. И поскольку my_pointer указывает на начало массива символов, именно это он и будет делать. Внутренне printf будет делать что-то вроде:
int printf(char* format, char* string)
{
    // process the format and find %s ...
    while (*string != '\0') // repeat until end of string
    {
        char c = *string;  // get the next character from the pointer address
        // print this character to the terminal
        ++string; // advance the pointer to the next character
    }
}


Member 13188016

Спасибо!!!!!!! Таким образом, тип данных указателя определяет его значение?
Например, char *my_pointer так что значение всегда только одно слово, как первое слово массива(?)
Если int *my_pointer, то значение равно number?
Для массива *my_pointer получает значение, на которое нацелен указатель, который является первым членом массива, поэтому тип данных всегда является char для массива?

Richard MacCutchan

Ну, не совсем. Атрибуты указателя определяются типом данных, на который он указывает. Так char* указывает на один символ и может быть увеличен по одному символу за раз для доступа к каждому элементу строки (массиву символов). Один int* указывает на 32-битный целочисленный тип и может увеличиваться через массив целых чисел по одному за раз. Другие указатели могут получить доступ long, double или даже типы структур и т. д. Взгляните на Введение в указатель на языке Си / учебник по языку Си | Studytonight[^] для получения дополнительной информации.

Рейтинг:
20

Rick York

Другой способ взглянуть на звездочку - это оператор разыменования указателя. Он получает значение, когда указатель направлен, которая для массива, первый элемент массива.

В printf %s ссылается на строку, массив символов, поэтому адрес массива должен быть передан. Флаг формата %c предназначен для одного символа, поэтому printf ожидает один член массива для этого спецификатора. Выходные данные отличаются тем, что спецификаторы формата сообщают функции printf, как интерпретировать передаваемые данные. Данные передаются в стеке функции в виде либо указателя, либо значения. Если формат неверен для данных в стеке, то функция либо выдаст странный вывод, либо приведет к сбою программы.


Member 13188016

Спасибо, что ответили на мои вопросы!!!
Но все же путают в какой-то части, поэтому значение where pointer, направленное в массив, всегда является первым элементом массива, но на самом деле внутри указателя находится все слова address или только первый элемент address?
Это означает, что *my_pointer содержит только адрес первого слова?
В то время как my_pointer ссылается на адрес целых слов?
Есть ли какая-то связь и с типом данных char?

типа char *my_pointer;
my_pointer = строка;
С my_pointer-это указатель на char, значение my_pointer адрес, который указывает на тип char.
Тип данных char относится только к одному слову, например "h", или ко всем словам?

Rick York

Указатель нацелен на первый элемент массива, но это место в памяти-только первый элемент. Остальные пункты продолжают его в памяти. Вот как работают массивы.

Фраза *my_pointer означает значение по адресу, содержащемуся в my_pointer.

Это соглашение применяется ко всем типам данных, а не только к символам.

Рейтинг:
12

CPallini

Потому что они действительно разные звери. Я бы посоветовал вам прочитать учебник по этой теме, например: Все, что вам нужно знать о указателях в C[^].


Member 13188016

Спасибо за рекомендацию!!! Прочтите его для лучшего понимания!!

CPallini

Добро пожаловать.