Есть ли что-то не так, если вы производите двойной указатель на указатель char? Цель в следующем коде состоит в том, чтобы изменить один элемент тремя разными способами.
double vec1[100];
double *vp = vec1;
char *yp = (char*) vp;
vp++;
vec1[1] = 19.0;
*vp = 12.0;
*((double*) (yp + (1*sizeof (vec1[0])))) = 34.0;
Броски этого типа попадают в категорию "ОК, если вы знаете, что делаете, но опасны, если вы этого не сделаете".
Например, в этом случае вы уже знаете значение указателя "yp" (оно указывало на double
), поэтому технически безопасно увеличивать его значение на величину double
и повторно отбрасывать обратно в double*
.
Контрпример: предположим, вы не знали, откуда пришел char*
скажем, он был предоставлен вам как параметр функции. Теперь ваш бросок будет большой проблемой: поскольку char*
технически выравнивается по 1 байт, а double
обычно выравнивается по 8 байт, вы не можете быть уверены, что вам дали 8-байт-выровненный адрес. Если он выровнен, ваша арифметика приведет к действительному double*
; если нет, то он будет разбит при разыменовании.
Это всего лишь один пример того, как отбрасывание может пойти не так. То, что вы делаете (на первый взгляд), похоже, что это сработает, но в целом вам действительно нужно обратить внимание, когда вы бросаете вещи.
С новыми процессорами INTEL основной проблемой, с которой вы можете столкнуться, является выравнивание. Скажите, что вы должны написать что-то вроде этого:
*((double*) (yp + 4)) = 34.0;
Тогда вы, вероятно, будете иметь ошибку времени выполнения, потому что double должен быть выровнен по 8 байтам. Это также верно для процессоров, таких как 68k или MIPS.
Это похоже на структуру и выполнение бросков по этой структуре. Вы вряд ли сломаете вещи.
В большинстве случаев, если вы можете этого избежать, ваш код будет намного сильнее. Лично я даже не использую такие приведения при чтении файла. Вместо этого я получаю данные из файла и помещаю их в структуру по мере необходимости. Скажем, я прочитал 4 байта в буфере для преобразования в целое число, я бы написал что-то вроде этого:
unsigned char buf[4];
...
fread(buf, 1, 4, f);
my_struct.integer = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
Теперь я не сделал уродливого броска, и я мог контролировать конечную цель целого в файле, независимо от того, какой конечный элемент процессора вы используете.
sizeof
отдельных элементов, поэтому проблем с выравниванием не возникает.
char*
если у вас под vec1
массив vec1
? Мне кажется странным, что он использовал sizeof(vec1[0])
вместо sizeof(double)
но не нашел его релевантным моему ответу.