Я инициализирую 2 массива так:
x = (double*) malloc(sizeof(double)*n);
xPlus1 = (double*) malloc(sizeof(double)*n);
Во-первых, я не уверен, что именно сейчас представляет собой x или xPlus1, указатель на массив, полный двойников, или массив, полный указателей на двойники? : /
Ответ на этот вопрос, вероятно, влияет на это, но если я выполняю эти различные операции, я не могу заставить его делать то, что я хочу, а именно копировать значения из xPlus1 в x. xPlus1 и x содержат разные значения для каждого индекса, потому что печать после простого цикла for дает желаемый эффект:
for (int i = 0; i < n; i++) {
x[i] = xPlus1[i];
}
Но используя ...
memcpy(x, xPlus1, sizeof(x));
memcpy(x, &xPlus1, sizeof(x));
Если я обращаюсь к x после любого из них в той же функции, x не изменяется, сохраняются старые значения.
memcpy(&x, &xPlus1, sizeof(x));
Я считаю, что это заставляет x и xPlus1 указывать на одно и то же место в памяти по выходным данным, которые я получаю. Это потому, что если я изменю x или xPlus1 после этой копии, то оба значения изменятся, если я напечатаю оба массива.
memcpy(&x, xPlus1, sizeof(x));
Умирает, исключение: необработанное исключение по адресу 0x011D5626 в MPITemplate.exe: 0xC0000005: место записи нарушения прав доступа 0x00000000.
Амперсанд в функциях обычно указывает на передачу по ссылке, как это происходит при передаче в memcpy и какая разница, если в конце концов он будет записывать в те же блоки?
Я был бы признателен, если бы кто-нибудь мог подробно рассказать мне, что происходит с этими операциями, потому что я могу возиться, заставляя их работать, но я лучше понимаю, что на самом деле происходит, когда эти вызовы выполняются.
Благодарность,
Майк
3 ответа
Я инициализирую 2 массива так:
Нет, ты не. Вы не показали определение x
и xPlus1
, но если это массивы, например:
double x[10];
Ваш код не компилируется. Предполагая, что ваш код компилируется, x
и xPlus1
являются указателями на удвоение. Они близки, но не одно и то же.
Во-первых, я не уверен, что именно сейчас представляет собой x или xPlus1, указатель на массив, полный двойников, или массив, полный указателей на двойники? : /
Опять же, вы должны опубликовать их определение, и тогда ваш вопрос не будет иметь никакого смысла. Это указатели, и все, что вы им назначаете, не меняет этого факта. Таким образом, это указатели, содержащие адрес размера блока памяти sizeof(double) * n
. Что будет в этой памяти, зависит от вас, вы можете рассматривать это как массив двойников или что-то еще, размер которого меньше или равен sizeof(double) * n
.
Но используя ...
memcpy(x, xPlus1, sizeof(x));
memcpy(x, &xPlus1, sizeof(x));
Итак, первая строка кода копирует sizeof (double *), вероятно, 8 байтов, то есть одно двойное (что является просто совпадением, что на 64-битной платформе sizeof (double *) == sizeof (double)) из памяти, на которую указывает xPlus1
, в память указано x
. Итак, вы в основном скопировали один элемент, такой же, как (если вы используете 32-битную платформу, вы бы просто скопировали половину double):
x[0] = xPlus1[0];
Вторая строка копирует память, где указатель xPlus1
находится на блоке памяти, на который указывает x
. Итак, вы скопировали double *
в double
x [0], что не имеет особого смысла:
x[0] = (double) xPlus1;
Этот код:
memcpy(&x, &xPlus1, sizeof(x));
В основном это сделал (просто запутанный способ):
x = xPlus1;
Следующий код:
memcpy(&x, xPlus1, sizeof(x));
Эквивалентно этому:
x = (double *)xPlus1[0];
Что заставляет указатель x
иметь мусорный адрес, что приводит к исключению.
Итак, ваш фактический код должен быть:
memcpy( x, xPlus1, sizeof( double ) * n );
И x
, и xPlus1
должны быть типа double*
. Это указатели на массив двойников n
.
Итак, когда вы это сделаете:
memcpy(x, xPlus1, sizeof(x));
Поскольку x
- это просто double*
, он копирует только sizeof(double*)
байтов ... то есть 8. Что вы хотите сделать:
memcpy(x, xPlus1, n * sizeof(*x));
Поскольку тип *x
- double
, поэтому n * sizeof(*x)
будет общим байтом памяти, принадлежащей xPlus1
: n
double
s.
x[0]
... независимо от того, эти 8 байтов будут неким допустимым значением double
- возможно, ваше назначение просто случайно не изменило младшие 4 байта.
Вы не учли декларации.
Добавляя тип,
double* x = (double*) malloc(sizeof(double)*n);
Проясняет, что x
является указателем на double
.
В этом конкретном случае двойное x
указывает на первый элемент в массиве двойных n
.
Что-то вроде этого:
(------- n doubles -----)
___________________________
x ===>| | | | | | | | | | | | | |
---------------------------
&x
даст вам адрес самой переменной x
. Это сильно отличается от адреса, который содержит переменная x
.
(Если у вас есть int x = 1;
, &x
, скорее всего, не будет 1.)
memcpy
принимает два указателя, один на адресат, а другой на источник, и размер копируемой памяти.
Но sizeof(x)
не дает вам размер выделенного вами массива; он дает вам размер x
, который является указателем.
(Размер измеряется в кратных sizeof(char)
, который по определению равен 1, а sizeof(double*)
будет 4 (32 бита) или 8 (64 бита) на большинстве современных машин. Таким образом, вы копируете 32 или 64 бит.)
Параметр размера должен быть того же размера, который вы передали в malloc
, если вы хотите скопировать все это целиком.
Указатели должны быть теми, которые возвращаются из malloc
, поскольку это блоки памяти, которые вы хотите скопировать.
Так,
memcpy(x, xPlus1, sizeof(double) * n);
Должен работать как ожидалось.
Похожие вопросы
Связанные вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.
xPlus1
УЖЕ является указателем на malloc'd памяти. когда вы выполняете&xPlus1
, вы получаете адрес самого указателя, а НЕ память malloc'd. например вы не копируете в свой блок malloc, вы копируете туда, где существует указатель, и уничтожаете все, что идет после него.memcpy(x, xPlus1, n * sizeof(double));
?double
, указывающий на блок памяти, выделенный для двойных элементовn
.xplus1
тоже делает то же самое, но они находятся в разных местах памяти. если вы напечатаете адреса для всехx
иxplus1
, вы увидите, что все они разные. Если вы используете & x в качестве аргумента, вы используете указатель указателя, что неверно. Исключение, которое вы получили, в основном говорит вам, что из-за того, что вы одновременно копировали, записывали и читали из одного и того же места, у вас есть проблемы с доступом.void * memcpy ( void * destination, const void * source, size_t num );
, вы ясно увидите, что выполнениеmemcpy(x, xPlus1, sizeof(x))
полезно для вас. Кроме того, битconst source
означает, что ваши исходные данные не изменяются, что вы в конечном итоге сделали и получили ошибку нарушения прав доступа при попытке использовать указатель указателя.