Проверьте, имеет ли массив двумерных указателей значение, определенное пользователем в C? - PullRequest
1 голос
/ 31 декабря 2010

Пример кода:

float** a;  
a = (float**) malloc(numNodes * sizeof(float*));  
for(int i=0; i<`numNodes`; i++)  
{  
    a[i] = (float*)malloc((numNodes-1) * sizeof(float));  
}

Я создаю динамический 2d массив выше. Перед заполнением я заметил, что каждый блок в массиве уже содержит это значение: -431602080.000000, а не NULL. Почему это?
Бывают ситуации, когда используются не все пробелы в массиве.
Итак, мой запрос прост: есть ли элегантный способ проверить, имеет ли каждый блок это значение по умолчанию или пользовательское значение?

Заранее спасибо.

Ответы [ 5 ]

2 голосов
/ 31 декабря 2010

Содержимое памяти, выделенной с помощью malloc (а также переменных, выделенных в стеке), равно undefined , поэтому вполне может быть что угодно. Обычно вы получаете пространство, заполненное нулями (потому что ОС закрывает страницы памяти, которые использовались другими процессами) или остатки предыдущего использования этих страниц памяти (это часто имеет место, если страница памяти принадлежала вашему процессу), но это что происходит под капотом, стандарт С не дает никаких гарантий.

Итак, в общем случае нет «значения по умолчанию» и нет способа проверить, была ли изменена ваша память; однако вы можете инициировать блоки памяти, которые вы используете, с магическими значениями, которые, как вы уверены, не будут использоваться в качестве «реальных данных», но это будет просто соглашение, внутреннее для вашего приложения.

К счастью, для переменных с плавающей запятой есть несколько магических значений, таких как тихий NaN, который вы можете использовать для этой цели; в общем, вы можете использовать макрос NAN, определенный в <math.h>, чтобы установить float в NaN.

Кстати, вы не должны читать неинициализированные float s и double s, поскольку обычный формат, в котором они хранятся (IEEE 754), содержит некоторые магические значения (например, сигнальный NaN), которые могут вызывать арифметические исключения когда они читаются, поэтому, если ваша неинициализированная память содержит такой битовый шаблон, ваше приложение, вероятно, завершится сбоем.

1 голос
/ 31 декабря 2010

Расширяя хороший ответ Matteo Italia:

Код инициализации одного массива будет выглядеть так:

float* row;

row = malloc( numNodes*sizeof(float) );
for (int i=0; i<numNodes; ++i) {
    row[i] = nanf(); // set a Not-a-Number magic value of type float
}

(я оставлю вам право изменить это для вашего многомерного массива)

Тогда где-то:

float value = ...; // read the array
if (isnan(value)) {
    // not initialized
} else {
    // initialized - do something with this
}

Важно помнить одну вещь: NaN == NaN выдаст false , поэтому лучше использовать isnan(), а не == для проверки наличия этого значения.

1 голос
/ 31 декабря 2010

C среды выполнения не требуются для инициализации памяти, которую вы сами не инициализировали, и значения, которые они содержат, по сути являются случайным мусором, оставшимся с момента последнего использования памяти.Сначала вам придется явно установить их все в NULL или использовать calloc.

0 голосов
/ 31 декабря 2010

Перед заполнением я заметил, что каждый блок в массиве уже содержит это значение: -431602080.000000, а не NULL.Почему это так?

malloc() не инициализирует выделенную память.Вам нужно использовать calloc(), если хотите 0 initialization

void *calloc(size_t nelem, size_t elsize);

Функция calloc() выделяет неиспользуемое пространство для массива nelem элементов, каждый из которых имеет размер elsize в байтах.Пробел должен быть инициализирован для всех битов 0.

0 голосов
/ 31 декабря 2010

В C автоматические переменные не инициализируются автоматически. Вам нужно явно установить переменную в 0, если это то, что вы хотите.

То же самое верно для malloc, который не инициализирует пространство в куче, которую он выделяет. Вы можете использовать calloc, если хотите инициализировать его:

a = malloc( numNodes*sizeof(float*) ); // no need to initialize this
for ... {
  a[i] = calloc( numNodes-1, sizeof(float) );
}
...