Домашняя страница автора: paper jie's blog_CSDN blog - язык C, подробное поле алгоритма blogger
Автор этой статьи: Привет всем, я бумажный цзе, спасибо за чтение этой статьи, добро пожаловать на создание трех компаний.
Эта статья включена в колонку «Язык C», тщательно составленную для студентов колледжей и начинающих программистов. Автор тратит много денег (времени и энергии) на его создание и обладает всеми базовыми знаниями языка C. Надеюсь, это поможет читателям.
Другие столбцы: «Системный анализ языка Си», «Подробное объяснение алгоритма», «Язык Си — Грамматика».
Обмен контентом: в этом выпуске восемь тестовых вопросов помогут вам преодолеть указатель Дорогие дедушки, пожалуйста, отодвиньте скамейку и присядьте.
-------- Не надо 998, не хочу 98, всего одна кнопка на три раза, при покупке три раза денег не потеряешь, не обманешь
предисловие
В предыдущей статье об указателях мы использовали несколько тестовых вопросов, чтобы всесторонне и многогранно объяснить взаимосвязь между указателями и массивами. В этой статье мы воспользуемся восемью классическими вопросами теста указателя, чтобы всесторонне и многогранно понять указатели.
Первый вопрос
Сколько стоит ответ? Почему этот ответ?
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
анализировать
Во-первых, мы знаем: а — это адрес первого элемента массива, а &а — весь вынутый адрес. Итак, a+1 — это адрес второго элемента, а разыменование равно 2. &a+1 — пропустить весь массив.После 5 элементов принудительный тип — int, что означает, что единицей сложения и вычитания адреса за ним является тип int. ptr — это адрес &a+1, поэтому ptr-1 должен вычесть тип int вперед, указывая на адрес 5, а разыменование равно 5.
второй вопрос
Предположим, что значение p равно 0x100000. Каковы значения выражений в следующей таблице?
Известно, что размер переменной структуры Test type составляет 20 байт.
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
анализировать
Через подсказку мы знаем, что это тип указателя структуры размером 20 байт и адресом 0x100000. 0x1 — это p+1, чтобы добавить тип структуры размером 20, то есть 0x100000+20=0x100014. unsigned long p — это преобразование p в целочисленный тип, добавление 1 к целочисленному типу — это добавление 1. Результат: 0x100000+1=0x100001 unsigned int* p — это преобразование p в тип указателя, поэтому p+1 — это добавить указатель размером 0x100000+ 4=0x100004
третий вопрос
Какой ответ? Почему это так?
int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf( "%x,%x", ptr1[-1], *ptr2);
return 0;
}
анализировать
a — это адрес первого элемента, &a+1 берет адрес всего массива int*(&a+1) — это преобразование типа &a+1 в тип int*, ptr[-1] может быть понимается как *(ptr- 1), ptr равен &a+1, поэтому ptr-1 должен вычесть размер типа int*, поэтому по адресу элемента 4 разыменование равно 4 int a для преобразования адреса a в целое число, а добавление 1 к целому числу означает добавление 1, мы также знаем, что адрес в памяти является байтом, добавьте здесь 1, поэтому содержимое, на которое указывает a+1, будет от 00 до 02 0x02000000
четвертый вопрос
Какой ответ? почему?
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);
return 0;
}
анализировать
Путем наблюдения: мы можем обнаружить, что в массиве есть () , поэтому это выражение с запятой, а значение справа зарезервировано, поэтому значение в () равно 1, 2 и 3 заполнено 0, за которым следует 0, поэтому массив. Средний макет выглядит так, как он выглядит после рисования.
p — это адрес a[0], а a[0] — это первая представленная строка, мы можем понимать a[0] как имя массива первой строки, поэтому a[0] — это адрес первого элемента, разыменование равно 1
пятый вопрос
Сколько стоит ответ? Почему это так?
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
анализировать
Массив a представляет собой двумерный массив с пятью строками и пятью столбцами, a — это адрес начального элемента, адрес a присваивается p, а q — указатель массива, а тип p — int[4].
Следовательно, каждый раз, когда добавляется p, пропускаются 4 элемента, поэтому p[4] эквивалентно *(p+4). Адрес p — это адрес после рисования картинки, а результатом вычитания двух адресов является число промежуточных элементов, поэтому &p[4][2 ]-&a[4][2]=-4
Мы знаем, что то, что хранится в компьютере, является дополнительным кодом. Если 100 напечатано
с
% P, дополнительный
код
напрямую печатается как адрес и
печатается с %d или - 4
Шестой вопрос
Сколько стоит ответ? Почему это так?
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int *)(&aa + 1);
int *ptr2 = (int *)(*(aa + 1));
printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;
}
анализировать
aa — это адрес первого элемента, который является адресом первой строки, а aa извлекает адрес всего двумерного массива
ptr1=&aa+1 &aa+1 преобразуется в тип int*, поэтому ptr-1 равен чтобы вычесть размер типа int* , в это время ptr указывает на адрес 10 элементов, разыменованных как 10
aa+1 это адрес первой строки плюс 1 на адрес второй строки, мы обнаружили, что тип aa +1 также является int*, предыдущий int* бесполезен. Его можно понимать как: int*ptr=*(aa+1), мы можем понимать *(aa+1) как aa[1], aa[1] — имя второго строкового массива, который является адресом первого элемент, и поскольку ptr==*(aa+1)==aa[1], поэтому ptr-1 указывает на элемент 5, разыменование равно 5
Седьмой вопрос
Сколько стоит ответ? Почему это так?
#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
анализировать
Нам нужно знать элемент типа char*, хранящийся в массиве a, который является адресом первого элемента работы, at и alibaba
Используйте вторичный указатель для хранения адреса a, pa==a, pa++==a++, a — адрес первого элемента, pa++==a++ — адрес второго элемента.
*pa — адрес первой буквы at, %s — напечатать эту строку символов через адрес первого символа
Вопрос восьмой
Сколько стоит ответ? Почему это так?
int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp+3);
printf("%s\n", *cpp[-2]+3);
printf("%s\n", cpp[-1][-1]+1);
return 0;
}
анализировать
Массив c хранит адрес первого элемента строки, массив cp хранит адрес адреса первого элемента, а cpp хранит адрес cp. Здесь также нужно обратить внимание на один момент: ++ и -- напрямую меняют свои значения, что повлияет на последующие расчеты.