Должен ли этот указатель действовать таким образом? Баси c C - PullRequest
2 голосов
/ 09 мая 2020

Насколько я понимаю, pName должен быть указателем со значением ячейки памяти char name.
Это означает, что когда я разыменую указатель переменной pName во втором операторе printf , он должен просто напечатать строку символов «Кэмерон». НО ЭТО НЕТ! Может ли кто-нибудь помочь этому нубу :)?

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char name[] = "Cameron";
    char * pName = &name;

    printf("Printing string of characters: %s\n", name);
    printf("Dereferencing pointer and printing string: %s\n", *pName);
    printf("Printing pointer: %p\n", &name);
    printf("Printing pointer another way %p\n", pName);

    return 0;
}

Ответы [ 3 ]

2 голосов
/ 09 мая 2020

pName - это char*, указатель на char. Итак, когда вы выполняете *pName, вы получаете char, который не является строкой, которую вы можете напечатать с помощью %s.

Вместо

char *pName = &name;

вам нужно:

char (*pName)[] = &name; // a pointer to an array of chars.

Теперь ваше разыменование / printf будет работать, как ожидалось.

Также формат %p требует, чтобы его аргумент имел тип void*. Таким образом, вам нужно привести аргументы к void* в вызовах printf.

См. 7.21.6.1 Функция fprintf :

p Аргумент должен быть указатель на void. Значение указателя преобразуется в последовательность печатаемых символов способом, определяемым реализацией.

0 голосов
/ 09 мая 2020

1.

char name[] = "Cameron";

char * pName = &name;

При инициализации pName, name уже распадается на указатель на первый элемент массива name, фактически name[0].

Таким образом, &name - это указатель на массив из 8 символов, тип char (*)[8], а не char*. Недопустимо присвоение char* char (*)[].

Это должно было дать вам диагностику c. Никогда не игнорируйте предупреждения компилятора.

Вместо этого используйте:

char * pName = name;

.

2.

printf("Dereferencing pointer and printing string: %s\n", *pName);

Спецификатор преобразования %s ожидает аргумент типа char *, который уже есть pName. При разыменовании pName получается недопустимый char.

Вместо этого используйте:

printf("Dereferencing pointer and printing string: %s\n", pName);

.

Примечание:

Чтобы соответствовать стандарту, %p должен иметь аргумент типа void*.

0 голосов
/ 09 мая 2020

Это объявление массива символов

char name[] = "Cameron";

эквивалентно следующему объявлению

char name[8] = { 'C', 'a', 'm', 'e', 'r', 'o', 'n', '\0' };

Это тип объекта name - char[8].

Вы можете написать, например, используя typedef

typedef char T[8];

, а затем объявить массив как

T name = { 'C', 'a', 'm', 'e', 'r', 'o', 'n', '\0' };

Таким образом, объявление указателя на массив будет выглядеть как

T *pName = &name;

где T, как было показано выше, равно char[8]. Таким образом, заменив псевдоним для типа, который он обозначает, у вас будет

char ( *pName )[8] = name;

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

printf("Dereferencing pointer and printing string: %s\n", *pName);

Разыменование указателя *pName дает lvalue массива, который, в свою очередь, неявно конвертируется в указатель на его первый элемент и имеет тип char *. Таким образом, чтобы использовать спецификатор преобразования %s yo должен предоставить выражение типа char *.

Что касается этого объявления

char * pName = &name;

, когда оно неверно, потому что в левой части есть объект типа char *, в то время как в правой части находится выражение типа char ( * )[8], и нет неявного преобразования из одного типа в другой.

Вы можете просто написать

char * pName = name;

Как было сказано выше, lvalue массива неявно конвертируется в указатель на его первый элемент и имеет тип char *. И вы можете писать с помощью этого указателя

printf("Dereferencing pointer and printing string: %s\n", pName);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...