Когда я читал книги о языке C, указатель на два уровня беспокоил меня много.
char s[5][5];
char *s[5];
char (*s)[5];
так в чем разница между ними?
Когда я читал книги о языке C, указатель на два уровня беспокоил меня много.
char s[5][5];
char *s[5];
char (*s)[5];
так в чем разница между ними?
В C лучше сказать декларацию. Затем он становится интуитивным. Для этого вы следуете правилу слева. Вот как это делается:
char *s[5];
Как вы это говорите? Для этого вы начинаете справа от имени переменной s
, а затем идите влево. Итак, вы начинаете с того, что "s есть a/an". Справа вы видите []
, и вы говорите, что s - массив... ". И затем вы идете влево и видите *
, и говорите, что s - массив указателей. И это то, что есть. Это массив из 5 указателей. Вы можете хранить различные указатели в этом массиве.
Теперь для другого:
char (*s)[5];
Вы начинаете так же. "s является a/an", а затем просмотрите ()
. Все, что находится внутри ()
, привязано к s
ближе чем что-либо снаружи. Таким образом, *
более тесно связан с s
чем []
. Итак, теперь вы говорите: "s - это указатель...", и теперь вы выходите из круглой скобки и смотрите []
. Итак, вы продолжаете: "s является указателем на массив". И это именно то, что есть. Это указатель, который указывает на первый элемент массива.
Теперь следуйте той же логике и попытайтесь угадать, что будет:
int (*callme)(int a, int b)
int (*callme[10])(int a, int b)
Подсказка, последняя может использоваться для создания таблиц поиска для функций.
Изменить:
Как уже упоминалось в комментариях, в начале есть также char
. Я никогда не мог найти простой способ говорить об этом, но, как правило, ясно из контекста. Например, в первом примере char
определяет тип массива, а во втором - определяет указатель. В упражнениях, которые я опубликовал, int
определяет тип возвращаемых значений функций. Как правило, с такими определениями будет только один элемент с типом undefined. И вот как я понимаю, где идет тип.
В то время как объявление было рассмотрено, возможно, следует указать на различия в использовании:
char s[5][5];
-
s
указывает на область выделенной памяти (куча, если глобальная, стек, если она локальная),s[0][0]
.. s[4][4]
(или в s[0]
.. s[24]
),sizeof(s)
== 25. char *s[5];
-
s
указывает на область выделенной памяти (куча, если глобальная, стек, если она локальная),s[0]
.. s[4]
,sizeof(s)
== 40 (*). char (*s)[5];
-
s
указывает не на любую выделенную память - это просто неинициализированный указатель в этой точке,&s
,sizeof(s)
== 8 (*).(*) note: предполагается 64-битная архитектура.
1.char s [5] [5];
Здесь s - двумерный массив с 5 строками и 5 столбцами. Где в этих 5 строках и 5 столбцах вы сохраните элемент символа типа.
2.char * s [5]; s - одномерный массив с 5 элементами, каждый элемент имеет указатель типа на символ.
3.char(* s) [5]; s - это указатель здесь не массива. S указывает на массив символов. например,
char arr[5][5];
char(*s)[5];
s = arr;
s [0] [0] будет таким же, как массив из arr [0] [0]