2016-04-28 5 views
1

Я могу создать двумерный массив в C++ следующим образом. Но мне трудно понять адреса памяти.адрес в динамическом двумерном массиве в C++

(Пожалуйста, обратите внимание на последнюю строку моего кода, где я пытаюсь напечатать десятичные значения ячеек памяти.)

#include <cstdio> 
#include <iostream> 

using namespace std; 

#define rowSize 3 
#define colSize 4 


int main(){ 
    int ** p; 

    p = new int*[rowSize]; 

    for(int i = 0; i < rowSize; i++){ 
     p[i]= new int[colSize]; 
    } 

    printf("the size of int**: %d\n", sizeof(int**)); 
    printf("the size of int*: %d\n", sizeof(int*)); 
    printf("the size of int: %d\n\n", sizeof(int)); 



    printf("%d %d", p[0], p[1]); 
    return 0; 
} 

Я использовал GCC версии 4.7.1 (ТДМ-1) компилятор и побежал мой программа на моем Windows 10-бит бит.

Вот пример вывода:

размер междунар **: 4

размер междунар *: 4

размер междунар: 4

Итак, вот мои два вопроса:

  1. Почему адреса отличаются на 24 вместо 16 (= 4 * 4)? Размер int равен 4 и есть 4 столбца в строке. Разве они не должны отличаться на 16? Я знаю про байтовое дополнение в структуре в C++. Что-то в этом причина этого?

  2. Я попытался изменить colSize 5:

    #define colSize 5 и перекомпилировать и снова запустили программу.

    Выход образца:

the size of int**: 4 

the size of int*: 4 

the size of int: 4 


7151960 7151992 

На этот раз адреса отличаются 32. Если байт обивка была причина, в 5 колонок потребует 5 * 4 = 20 байт. В этом случае достаточно заполнить 4 байта, и в этом случае адреса должны отличаться на 24.

Так почему же в этом случае они отличаются друг от друга на 32?

+0

Какой ответ (ы) вы ожидаете? Объяснение деталей реализации gcc? Или «Как вопрос будет сформулирован, это те детали, которые не гарантированы, вы не должны делать прогнозы о них, но если вам нужно полагаться на X и Y, используйте это ...» достаточно? – VolkerK

+0

Попробуйте то же самое с реальным 2d массивом: int p [3] [4]; –

+0

Да, тогда их разность может быть рассчитана. Но меня больше интересовало понимание того, возвращает ли 'new int [colSize]' адрес в некотором шаблоне. –

ответ

2
  1. Результат операции выделения памяти alignof(std::max_align_t) -aligned. В вашем случае alignof(std::max_align_t), вероятно, 8.
  2. В большинстве реализаций имеется невидимое количество байтов sizeof(std::max_align_t), выделенных рядом с массивом для некоторой внутренней бухгалтерии. В вашем случае это, вероятно, имеют размер 8.

Таким образом, в первом случае: 4 * 4 + 8 = 24, уже кратно 8.
Во втором: 4 * 5 + 8 = 28, закругленные до ближайшего умножения на 8 = 32.

Компилятор не обязан возвращать возрастающий адрес или следовать некоторому шаблону. Просто случилось, что это самое легкое в твоем случае.

+0

Я использовал 'printf ("% d ", size_t);' и получил 4 результата. Но спасибо, мне было любопытно, когда мы каждый раз находили ту же самую разницу. –

+0

@AhsanTarique немного исправил мой ответ, чтобы быть более точным. Я забыл, что size_t не является максимальным типом псевдонимов для 32-битных машин –

-1

Вы не пишете C++, но C. Как помечено это как C++, я предполагаю, что вы хотите C++ ...

Современный C++ использует RAII и значительно упрощает сортировку вещей, используя стандартные библиотеки контейнеров. Хотя я знаю, что это не совсем ответ на ваш вопрос, я хотел бы предложить вам переписать код:

#include <vector> 
#include <cstdio> 
int main() 
{ 
    int rowsize = ...; 
    int colsize = ...; 

// allocating 
    std::vector<std::vector<int>> vec(rowsize); 
    for(auto e: vec) 
     e.resize(colsize); 

// filling with values 
    vec.at(row).at(col) = 123; 
// printing values 
    std::cout << vec.at(row).at(col) << std::endl; 
} 
1

Адреса в вашей arryas клеток p[i] определяются new оператора

р [i] = new int [colSize];

Этот оператор может вернуть любой адрес из кучи, и это не зависит от размеров массивов.

Вы можете создать один большой размерный массив (как компилятор делает array[][]) и сопоставить два измерения с одним измерением.

int* arr2d = new int[colSize*rowSize]; 
//Retrieve value from Row3 Col2 
int nRow3Col2 = arr2d[2 + 3 * colSize]; 
+0

Кажется, что они различаются по одной и той же длине при каждом прогоне (хотя адреса различаются). Поэтому я думал, что может быть шаблон вместо адресов, которые являются случайными. –

+0

Это зависит от реализации оператора 'new' (который может быть перегружен BTW). В любом случае addreses не гарантируются. Также попробуйте выполнить компиляцию в режиме «Release» и обратите внимание на разницу. –

+0

Боюсь, я не понял, что вы сказали о режиме выпуска. Я попытался это сделать и нашел это в одном из результатов. [link] (http://stackoverflow.com/questions/11253334/how-to-debug-in-release-mode) Должен ли я попробовать метод, ответивший на вопрос? –