Делает это так же, как и для любого другого типа данных. Массив "строк" на самом деле является массивом символьных указателей, которые все имеют одинаковый размер. Таким образом, чтобы получить правильный адрес для указателя , он умножает индекс на размер отдельного элемента, а затем добавляет его к базовому адресу.
Ваш массив будет выглядеть так:
<same-size>
+---------+
fmts: | fmts[0] | ------+
+---------+ |
| fmts[1] | ------|--------------------------+
+---------+ | |
V V
this one is a little long\0this one is short\0
Символы для самих строк не хранятся в массиве, они существуют в другом месте. Как у вас есть, они обычно хранятся в постоянном запоминающем устройстве, хотя вы также можете malloc
их или даже определить как модифицируемый массив символов с чем-то вроде:
char f0[] = "you can modify me without invoking undefined behaviour";
Вы можете увидеть это в действии со следующим кодом:
#include<stdio.h>
const char *fmts[] = {
"This one is a little long",
"Shorter",
"Urk!"
};
int main (void) {
printf ("Address of fmts[0] is %p\n", (void*)(&(fmts[0])));
printf ("Address of fmts[1] is %p\n", (void*)(&(fmts[1])));
printf ("Address of fmts[2] is %p\n", (void*)(&(fmts[2])));
printf ("\n");
printf ("Content of fmts[0] (%p) is %c%c%c...\n",
(void*)(fmts[0]), *(fmts[0]+0), *(fmts[0]+1), *(fmts[0]+2));
printf ("Content of fmts[1] (%p) is %c%c%c...\n",
(void*)(fmts[1]), *(fmts[1]+0), *(fmts[1]+1), *(fmts[1]+2));
printf ("Content of fmts[2] (%p) is %c%c%c...\n",
(void*)(fmts[2]), *(fmts[2]+0), *(fmts[2]+1), *(fmts[2]+2));
return 0;
}
который выводит:
Address of fmts[0] is 0x40200c
Address of fmts[1] is 0x402010
Address of fmts[2] is 0x402014
Content of fmts[0] (0x4020a0) is Thi...
Content of fmts[1] (0x4020ba) is Sho...
Content of fmts[2] (0x4020c2) is Urk...
Здесь вы можете видеть, что фактические адреса элементов массива равноудалены - 0x40200c + 4 = 0x402010
, 0x402010 + 4 = 0x402014
.
Однако значения не являются, потому что они относятся к разным размерам строк. Строки находятся в одном блоке памяти (в данном случае - ни в коем случае не нужно), как показано ниже, с символами *
, обозначающими начало и конец отдельных строк:
| +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f +0123456789abcdef
---------+-------------------------------------------------------------------
0x04020a0| *54 68 69 73 20 6f 6e 65 20 69 73 20 61 20 6c 69 This one is a li
0x04020b0| 74 74 6c 65 20 6c 6f 6e 67 00*53 68 6f 72 74 65 ttle long.Shorte
0x04020c0| 72 00*55 72 6b 21 00* r.Urk!.