Разница между 2D-массивом символов и char** (ИЛИ, 3D-массивом символов и char*** и т. д.)

Во-первых, я уже рассмотрел эти:

Как многомерные массивы форматируются в памяти?

Карта памяти для двумерного массива в C

Отсюда известно, что 2D-массив не то же самое, что и char**, но в памяти они выглядят точно так же. Это звучит странно, поэтому я исследовал следующее:

#include <stdio.h>

char func(char** m) {
    return m[0][0]; //only works for char**, already discussed in the other SO question
}

int main() {

    //char a[4][2]; //a 2D char array

    int row = 4, col = 2;   //char**
    char** a = malloc(row * sizeof(char*));
    int i;
    for (i = 0; i < row; i++) {
        a[i] = malloc(col * sizeof(char));
    }

    //checking the output
    printf("      &a = %u\n", &a);
    printf("   &a[0] = %u\n", &a[0]);
    printf("&a[0][0] = %u\n", &a[0][0]);
    printf("       a = %u\n", a);
    printf("    a[0] = %u\n", a[0]);

    //printf(" a[0][0] = %u\n", a[0][0]);   //char value in a[0][0], here a garbage value

    //char m = func(a); //only works for char**, already discussed in the other SO question

    return 0;
}

Возможный вывод для char** :

      &a = 3209288  //                  &a
   &a[0] = 4083720  // &(*(a+0))      =  a
&a[0][0] = 4083784  // &(*(*(a+0)+0)) = *a
       a = 4083720  //                   a
    a[0] = 4083784  // *(a+0)         = *a

Возможный вывод для массива 2D-символов:

      &a = 3473104  // &a
   &a[0] = 3473104  //  a
&a[0][0] = 3473104  // *a
       a = 3473104  //  a
    a[0] = 3473104  // *a

Легко понять вывод char**. Но вывод массива 2D-символов выглядит странно, хотя это обсуждалось в другом вопросе SO. Я не могу придумать указатель x любого типа данных, когда

x = &x = *x

и все три вещи физически находятся в одном блоке памяти. Надеюсь, что мое замешательство понятно. Кто-нибудь может объяснить загадку?

Отсюда известно, что 2D-массив не совпадает с char**, но в памяти они выглядят точно так же. Это не так.   —  person arnobpl    schedule 10.05.2014

См. также:  Непоследовательное поведение прослушивателя сущностей Doctrine

@self: я только что сослался на утверждение из других упомянутых вопросов SO. Я смущен.   —  person arnobpl    schedule 10.05.2014

Не могу найти эту цитату, можете указать?   —  person arnobpl    schedule 10.05.2014

@self: Не совсем цитата, но похожая вещь.   —  person arnobpl    schedule 10.05.2014

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. arnobpl

    Когда вы используете в качестве имени массива любое выражение, кроме &array и sizeof array, это имя будет автоматически преобразовано в указатель на первый элемент массива (char [5][10] будет преобразовано в char (*)[10]). Адрес этого указателя будет равен адресу всего массива.
    Итак, «sizeof (char [5][10]) == 50», дополнительных указателей нет.

    char arr[5][10];
    
    &a = 3473104 // Address of entire array, (char (*)[5][10])
    &a[0] = 3473104 // Address of first row, (char (*)[10])
    &a[0][0] = 3473104 // Address of first char, (char *)
    a = 3473104 // "a", (char [5][10]), converted to "&a[0]", (char (*)[10])
    a[0] = 3473104 // "a[0]", (char[10]), converted ro "&a[0][0]", (char *)
    

    Хороший ответ, хотя и не такой ясный, как я ожидал. Прочитав несколько статей, я понял, что массивы не являются указателями, и наоборот. Определенные особенности языка, кажется, сговорились, чтобы заставить меня думать, что они эквивалентны. На самом деле это не так. person arnobpl; 12.05.2014

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: