2015-02-19 1 views
2

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

void example(char *array) { 
    char temp[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };  
    memcpy(array, temp, sizeof(temp)); 
} 

Это работает довольно хорошо, но я искал способ сделать то же самое в пределах одной строки вместо двух. Кто-нибудь знает, как это сделать?

+1

Нет никаких преимуществ, чтобы сделать это на одной строке вместо двух ... ваш код уже идеален, когда дело доходит до читаемости и производительности. – Lundin

+0

Одна строка: 'char temp [] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; memcpy (массив, temp, sizeof (temp));' Просто удалите разрыв строки;) –

+0

Хмм , .. ну, мне нужно будет получить доступ к многим указателям, но если другого решения не будет, я буду делать это таким образом каждый раз. – Lui

ответ

5

Я пишу этот ответ, потому что вы прокомментировали, что хотите сделать это в одной строке, чтобы избежать «для доступа ко многим указателям». Но вы этого не сделаете. Любой достойный компилятор оптимизирует это. GCC с -O1 производит этот код на x86_64 для вашего примера, без изменений. Он даже не называет memcpy:

example: 
.LFB12: 
    .cfi_startproc 
    movb $1, (%rdi) 
    movb $2, 1(%rdi) 
    movb $3, 2(%rdi) 
    movb $4, 3(%rdi) 
    movb $5, 4(%rdi) 
    movb $6, 5(%rdi) 
    movb $7, 6(%rdi) 
    movb $8, 7(%rdi) 
    ret 
    .cfi_endproc 

Для объяснения: $1, $2 и т.д. элементы ваших буквального, и %rdi является регистром, который содержит первый аргумент example т.е. указателя вы с именем array.

Просто используйте две читаемые строки.

3

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

memcpy(array, "\x01\x02\x03\x04\x05\x06\x07\x08", sizeof("\x01\x02\x03\x04\x05\x06\x07\x08") - 1); 
+0

Почему '-1' в' sizeof (...) - 1'? –

+2

@CoolGuy, чтобы удалить '\ 0' – ForceBru

+1

Поскольку строки являются 0-гранными и мы не хотим копировать нуль в конце. ;-) – Lui

2

Вы можете использовать соединение буквального:

memcpy(array, (char []) {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 
     sizeof ((char []) {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08})); 

вы можете использовать, чтобы определить, не должны повторять массив (это более подвержены ошибкам, если вы должны изменить элементы массива):

#define ARRAY ((char []) {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}) 

memcpy(array, ARRAY, sizeof ARRAY); 
+0

Я думаю, вы пропустили «{», но я не могу отредактировать вам сообщение. :-( – Lui

+0

Ну, это выглядит красиво для меня, но я получаю «прием адреса временного массива» -Error. – Lui

+0

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

1

Предполагая, что машина LSB

*(unsigned long long *)array = 0x0807060504030201;

P.S. Ну, не считайте это слишком серьезным ;-)

P.P.S. Позвольте мне добавить другой аргумент против использования функции char[] (вместо static char[]).

Хотя оптимизирующий компилятор может иногда исключить раздражающую переменную стека, но это не всегда возможно. Рассмотрим, например, вызов какой-либо другой функции, скажем, printf("%s", temp). Это выглядит довольно невинно, но, как второй аргумент printf не известен как const, компилятор должен создать копию всего массиваtemp в стеке, перед передачей его в printf.

Для некоторого большого массива это может быть очень болезненно!

2

канонический способ писать код будет таким:

void example(char *array) { 
    static const char temp[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };  
    memcpy(array, temp, sizeof(temp)); 
} 

Это очень читаемый, а также самый быстрый, поскольку локальная константа не будет выделяться в стеке на один вызов функции.Но, конечно, это то, что компилятор, скорее всего, оптимизирует.

Нет причин, чтобы попытаться вручную оптимизировать этот код. Строковые литералы сделают код более трудным для чтения. Компонентные литералы будут обладать локальной областью и теоретически распределены в стеке для каждого вызова функции, что сделает код более медленным в теории - на практике компилятор, скорее всего, оптимизирует составной литерал, чтобы он не нажимался на стек для каждого вызов функции.

Если несколько функций должны использовать одну и ту же константу, тогда объявите ее в области файлов, но сохраните ее static const, чтобы вы не загромождали глобальное пространство имен больше, чем необходимо.

+0

В качестве побочного примечания существует _is_ разница между 'char',' static char' и 'static const char'. Вот код для игры с - http://ideone.com/8KsALZ См., Как меняется «temp». – Matt

+0

@ user4419802 Этого не ожидается без оптимизации. 'char' = stack,' static char' = .data, 'static const char' = .rodata. Если вы, однако, скомпилируете все оптимизации (например, gcc -o3), вы заметите, что получаете тот же адрес независимо от того, какую форму вы используете. Вот почему, например, исходный код или составные литералы не добавляют никаких накладных расходов, как упоминалось в моем ответе. – Lundin

+0

Когда оптимизация включена, никто, кроме самого компилятора, не может предсказать выходной код. Тем не менее, давая некоторый намек на компилятор, все еще хорошая идея. – Matt