#include <stdio.h>
для printf
и #include <string.h>
для memset
.
int main()
Вы можете уйти с этим, но int main(void)
лучше.
{
char *ptr;
char evil[4];
memset(evil, 0x43, 4);//fill evil variable with 4 C's
Это было бы более разборчивыми при замене 0x43
на 'C'
. Оба они означают одно и то же (при условии набора символов на основе ASCII). Еще лучше, если не повторять размер:
memset(evil, 'C', sizeof evil);
ptr = &evil[0];//set ptr variable equal to evil variable's memory address
Это устанавливает ptr
в адрес исходной (0-й) элемент массива объекта evil
. Это не то же самое, что адрес самого объекта массива. Они имеют одинаковое расположение в памяти, но &evil[0]
и &evil
имеют разные типы.
Вы также можете написать это как:
ptr = evil;
Вы не можете назначить массивы, но выражение массив, в большинстве контекстов, неявно преобразуется в указатель на начальный элемент массива.
Взаимосвязь между массивами и указателями в C может быть запутанной.
Правило 1: Массивы не указатели.
Правило 2: прочитайте раздел 6 раздела comp.lang.c FAQ.
printf(ptr);//prints 4 C's
Первый аргумент printf
должен (почти) всегда быть строковым, строка формата. Если вы укажете ему имя переменной массива символов, и в ней должно быть %
символов, могут быть плохие вещи. Если вы просто выводя строку, вы можете использовать "%s"
как формат строки: (. Заметь, что я добавил строку так отображается выход правильно)
printf("%s\n", ptr);
За исключением того, что ptr
Безразлично 't указывает на строку . Строка по определению заканчивается символом null ('\0'
). Ваш массив evil
не является. (Вполне возможно, что там просто бывает нулевые байты только после того, как массива в памяти Не зависит от этого.).
Вы можете использовать ширину в поле, чтобы определить, сколько символов в печать:
printf("%.4s\n", ptr);
Или, чтобы избежать ошибок, подверженных практике того, чтобы написать тот же номер несколько раз:
printf("%.*s\n", (int)sizeof evil, evil);
найти хороший документ для printf
если йо Вы хотите это понять.
(или, в зависимости от того, что вы делаете, может быть, вы должны организовать evil
быть нулевым байтом в первую очередь.)
printf(&evil);//prints 4 C's
Ах, теперь мы есть серьезные неопределенное поведение. Первый аргумент printf
является указателем на строку формата; это тип const char*
. &evil
имеет тип char (*)[4]
, указатель на массив из 4 char
элементов. Ваш компилятор должен был предупредить вас об этом (строка формата имеет известный тип, а следующие аргументы отсутствуют, поэтому правильность их типов зависит от вас). Если это кажется, то это связано с тем, что &evil
указывает на то же место в памяти, что и &evil[0]
, а разные типы указателей, вероятно, имеют одинаковое представление в ваших системах, и, возможно, бывает, что происходит случайный '\0'
сразу после массива - возможно, предшествующего некоторыми непечатаемыми символами, которые вы не видите.
Если вы хотите напечатать адрес вашего объекта массива, используйте формат %p
. Это требует аргумент типа указателя void*
, так что вам нужно бросить его:
printf("%p\n", (void*)&evil);
return 0;
}
Сведя все это вместе и добавив некоторые навороты:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *ptr;
char evil[4];
memset(evil, 'C', sizeof evil);
ptr = &evil[0];
printf("ptr points to the character sequence \"%.*s\"\n",
(int)sizeof evil, evil);
printf("The address of evil[0] is %p\n", (void*)ptr);
printf("The address of evil is also %p\n", (void*)&evil);
return 0;
}
Выход на моей системе является :
ptr points to the character sequence "CCCC"
The address of evil[0] is 0x7ffc060dc650
The address of evil is also 0x7ffc060dc650
C++ tag! Это ИЗВЕСТНО! – user4581301
'printf()' строки, не содержащей NULL, никогда не будет полезен. –
Массивы немного непоследовательны в языке: 'evil' и' & evil' означают одно и то же - это справедливо только для массивов. Кроме того, вам повезло, что 'printf' работает без наличия явных 0-терминираторов в вашем массиве символов. –