LINUX.ORG.RU

C: int->char[4] для printf/scanf


0

0

Очень нужно в программе, обрабатывающей огромное число записей (~2млн.) реализовать быстрое чтение и запись 4 символов. Я вижу самый простой путь - это занести символы в int:
int x;
char *z;
z = (char *)&x;
z[0] = val1;
z[1] = val2;
z[2] = val3;
z[3] = val4;

Вот как теперь, имея этот самый int вывести его через printf ?
printf("%4c", x) или printf("%c%c%c%c", x) не работают

Хочется реализовать именно так, чтобы было быстро. Уточнение насчет x: его возвращает функция, то есть в итоге я хочу получить что то вроде:
printf("%4c", myfunc(x))

В man сказано:
"%c If no l modifier is present, the int argument is converted to an unsigned char". То есть он считывает таки переменную, а не указатель. Как заставить его считать оттуда все 4 байта без конверсии? Если делать %lc, то он читает 2 байта, как я понял, а мне бы 4 :-)

P.S. Я понимаю, что printf/scanf можно переписать или переопределить, но быстро уже не будет :-(

★★★★★

Ограничение в 4 символа жесткое, оно не будет меняться.

saper ★★★★★
() автор топика

Можно и wcrtomb переписать, это будет проще, тем более я думаю она пишет по адресу формируемой строки для printf с парамтером %lc. Но может есть более оптимальный вариант?

saper ★★★★★
() автор топика

ИМХО для scanf нужно 4 разных аргумента. Посмотри, что происходит когда пересылаеш 4 char. Чтобы сработало, нужно

printf("%c%c%c%c", 0 [(char *) &x], 1 [(char *) &x], 2 [(char *) &x], 3 [(char *) &x]); где x - целое.

bugmaker ★★★★☆
()

Можеш поюзать union для упаковки char в int, но подставлять функцию в качестве агумента не выдет.

bugmaker ★★★★☆
()

Я бы сделал типо такого

union {
  unsigned log int x;
  char c [4];
} beda;

...

printf ("%c%c%c%c", (beda.x = myfunc (x), beda.c[0]), beda.c[1], beda.c[2], beda.c[3], beda.c[4]);

bugmaker ★★★★☆
()
Ответ на: комментарий от bugmaker

myfunc на один printf вызывается несколько раз :-(
сейчас это сделано так:
char tbuf[31][4] /* максимум в строке 31 вызов */

char *myfunc(char *cin, double param) {
/* тут идет обработка и заполнение cin */
return cin;
}

Соответственно вызывается myfunc так:
printf("%s %s %s ... %s", myfunc(tbuf[0], x0), myfunc(tbuf[1], x1), myfunc(tbuf[2], x2) ... myfunc(tbuf[n], xn));

Но тут пересылаются указатели, хорошо, что myfunc заполняет сразу выводимую printf строку. А хочется, чтобы myfunc записала в стек 4 байта, которые printf сразу отправит по назначению, т.е. запишет в файл, например если это был fprintf. Ведь для %c так и делается ...

saper ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Тем printf выводится еще несколько (7) параметров с форматированием, заданным в формате printf.

saper ★★★★★
() автор топика
Ответ на: комментарий от saper

по-моему если на каждую запись дёргать printf, то тут на преобразовании int/char особо ничего не выиграешь.

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

потом всегда можно будет посмотреть профайлером узкие места и их пытаться улучшать

anonymous
()
Ответ на: комментарий от saper

в стек кладутся итемы размером больше байта. Посему, всё равно придёцо раскидывать байты. Можно попробывать извтрат типо

x = myfunc (xy);

printf ("%c%c%c%c", (x >>= 8) & 0xFF, (x >>= 8) & 0xFF, (x >>= 8) & 0xFF, (x >>= 8) & 0xFF);

но ето изврат!

bugmaker ★★★★☆
()
Ответ на: комментарий от bugmaker

Похоже только так и придется делать, только write (int) ;-)

saper ★★★★★
() автор топика

> Очень нужно в программе, обрабатывающей огромное число записей (~2млн.) реализовать быстрое чтение и запись 4 символов. Я вижу самый простой путь - это занести символы в int:

Что-то я не осознал мысли. scanf("%c%c%c%c") в любом случае "не быстро". Может просто scanf("%4c") ? Я к тому, что к строчке из 4-х символов логичнее относится именно как к строчке из 4-х символов, а то, что вы думаете будет ускорением, так это, часто, нано-оптимизация, довольно спорная с точки зрения усложнения алгоритмов.

Casus ★★★★★
()
Ответ на: комментарий от saper

А нельзя ли сделать так:

int x = myfunc(); // содержит эти 4 символа
char buf[5] = { (char)(x&0xff), 
                (char)((x>>8)&0xff), 
                (char)((x>>16)&0xff), 
                (char)((x>>24)&0xff), 
                0 };
printf("%s", buf);

?

Я думаю, это весьма быстро.

GCC с ключами "-O2 -fomit-frame-pointer" рожает такой код:

call    myfunc
mov     [esp+1Ch+var_1C], al
sar     eax, 8
mov     [esp+1], al
sar     eax, 8
mov     [esp+1Ch+var_1A], al
sar     eax, 8
mov     [esp+1Ch+var_19], al
mov     [esp+1Ch+var_18], 0
sub     esp, 8
lea     eax, [esp+24h+var_1C]
push    eax
push    offset unk_8000045
call    printf

jek_
()

>реализовать быстрое чтение и запись 4 символов. Я вижу самый простой путь - это занести символы в int:

А где здесь ускорение? Почему бы не работать указателями на char* необходимыми тебе порциями?

>Вот как теперь, имея этот самый int вывести его через printf ?
printf("%4c", x) или printf("%c%c%c%c", x) не работают

Попробуй printf("%.4s", &x) - поможет.

>Хочется реализовать именно так, чтобы было быстро. Уточнение насчет x: его возвращает функция, то есть в итоге я хочу получить что то вроде:
printf("%4c", myfunc(x))

Если функция будет возвращать не сам x а указатель на него пойдет?
Тогда:
printf("%.4s", myfunc(x))
Ну или можешь проведения типов замутить.

KIV
()
Ответ на: комментарий от KIV

> Если функция будет возвращать не сам x а указатель на него пойдет?

Интересно, а где же будет храниться этот x? Не на стеке же! Если глобальной переменной, то вообще ничего возвращать не нужно... Но если рядом есть другие потоки, то глобал не пойдёт.

jek_
()
Ответ на: комментарий от jek_

>Интересно, а где же будет храниться этот x? Не на стеке же!

А почему бы и нет? Вообще, думаю из этого проблему не стоит зраздувать

>Если глобальной переменной, то вообще ничего возвращать не нужно...

Прежде чем писать, надо все внимательно читать :) Прочитай как первоначально вопрос был поставлен.

>Но если рядом есть другие потоки, то глобал не пойдёт.

Че ж так? Можно и глобал, только осторожно :) Но к обсуждаемой теме это не имеет ни малейшего отношения.

KIV
()
Ответ на: комментарий от KIV

> А почему бы и нет? Вообще, думаю из этого проблему не стоит зраздувать

Ага, вообще отличные советы даёшь! А ничего, что фрейм стека myfunc()
уже не активен и там может быть что угодно, мусор? Что, это пустяки?

> Прежде чем писать, надо все внимательно читать :) Прочитай как
> первоначально вопрос был поставлен.
> Че ж так? Можно и глобал, только осторожно :) Но к обсуждаемой теме
> это не имеет ни малейшего отношения.

Я помню, что вопросе "x возвращает функция". Я просто высказал мысль.
Конечно, осторожно нужно, кто же спорит. Но это медленно.

Можно, кстати, возвращать не int, а 64-битное значение, long long,
например. В этом случае символами заполнять младшую часть, а старшую
выставлять в 0. Вот, например, так:

long long myfunc() {
    long long x = 0x676e6f6c;
    return x;
}

int foo() {
    long long x = myfunc();
    printf("%s\n", (char*)&x);
}

В этом случае foo напечатает слово "long".

jek_
()
Ответ на: комментарий от jek_

>А ничего, что фрейм стека myfunc() уже не активен и там может быть что угодно, мусор?

А че за "фрейм стека" такой? И что значит "не активен"? Просто не встречал таких понятий. А вообще то компилятор должен нормально отработать такую ситуацию.

>Я просто высказал мысль. Конечно, осторожно нужно, кто же спорит.

Кстати заметь я тоже "просто высказал мысль" и "осторожно нужно, кто же спорит." :)

>Можно, кстати, возвращать не int, а 64-битное значение,

Я вообще так и не понял какое дает ускорение использование int вместо char*. Почему аффтар думвет что так быстрее, хз. :\

KIV
()
Ответ на: комментарий от KIV

> А че за "фрейм стека" такой? И что значит "не активен"? Просто не
> встречал таких понятий. А вообще то компилятор должен нормально
> отработать такую ситуацию.

Ну привет. Ты скажи ещё, что не знаешь, что такое стек, и какова
семантика функции в Си! Объясняю на пальцах. Локальные переменные
функции, вообще говоря, НЕЛЬЗЯ использовать вне этой функции, ни
по указателю, ни по ссылке (в случае С++), ни каким-либо ещё хитро...
эээ...-м способом.

> Я вообще так и не понял какое дает ускорение использование int вместо
> char*. Почему аффтар думвет что так быстрее, хз. :\

Ускорение ясно какое. Афтар хочет возвращать четыре символа
одновременно. Через параметры их возвращать неудобно (это же тот же
стек, косвенная адресация и прочая фигня). Целое число вмещает в себе
четыре символа и возвращается как содержимое регистра eax (на IA32).
Это быстрее, конечно, но IMHO последующий printf с семью параметрами
в шаблоне жрёт столько тактов, что мизерное ускорение от пакования
четырёх символов - просто тьфу.

jek_
()
Ответ на: комментарий от jek_

>Ну привет. Ты скажи ещё, что не знаешь, что такое стек, и какова семантика функции в Си! Объясняю на пальцах. Локальные переменные функции, вообще говоря, НЕЛЬЗЯ использовать вне этой функции, ни по указателю, ни по ссылке (в случае С++), ни каким-либо ещё хитро... эээ...-м способом.

Вот, хоть поздаровался :) 1. Я спрашивал про термины "Фрейм" и "неактивен" :) А не про тот как и где размещаются автоматические переменные. А делить стек на фреймы, следить за их активностью..... или что, всеже значит "неактивный фрейм"?

2. А причем тут локальные переменные? Я что где-то предложил возвращать указатель на ЛОКАЛЬНУЮ переменную?

3.Хитрые способы есть ;) - выделить под данные память и вернуть указатель. Объявить переменную static наконец.

>Ускорение ясно какое. Афтар хочет возвращать четыре символа одновременно.

А причем тут int то? Ну возвращай себе хоть сотню символов, через указатель char*, int то причем? Что обычно делают с данными? Считывают, анализируют, процессят, записывают. В каком случае нам помогает int? Учти что есть такая штука как кеширование :)

KIV
()
Ответ на: комментарий от jek_

>Локальные переменные функции, вообще говоря, НЕЛЬЗЯ использовать вне этой функции, ни по указателю, ни по ссылке (в случае С++), ни каким-либо ещё хитро... эээ...-м способом.

Вот пример: четко придерживаясь терминологии ты не прав.

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

Для переменных место под хранение которых выделяется неявно, например в стеке, используется термин "автоматические", это классика. ЗЫ. Сорри за оффтоп :)

KIV
()
Ответ на: комментарий от KIV

> или что, всеже значит "неактивный фрейм"?

Хорошо. "Неактивный фрейм" стека - эта область на стеке, лежащая за пределами границ стека. То есть то место на стеке, где _когда-то_ размещались локальные переменные процедуры.

> Я что где-то предложил возвращать указатель на ЛОКАЛЬНУЮ переменную?

Да. Вот этой фразой: "А почему бы и нет? Вообще, думаю из этого проблему не стоит зраздувать" в ответ на моё замечание ".. где же будет храниться этот x? Не на стеке же!"

> выделить под данные память и вернуть указатель. Объявить переменную > static наконец.

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

> В каком случае нам помогает int? Учти что есть такая штука как > кеширование :)

Да я же говорил уже - это позволяет вернуть четыре символа за раз на регистре.

> локальные переменные вне функции можно, статические например.

> Для переменных место под хранение которых выделяется неявно, > например в стеке, используется термин "автоматические", это > классика. ЗЫ. Сорри за оффтоп :)

Да, ты прав. В терминологии у меня некоторый бардак :)

jek_
()
Ответ на: комментарий от jek_

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

Блин загнул то. "Фрейм" е-мое :)

Я не говорю что это правильно и безопасно. Просто в программировании порой приходится применять так называемые "фитчи". Ну сам подумай наконец как в принципе будет выполняться printf("%.4s", myfunc(x)) если myfunc(x)возвращает указатель даже на переменную размещенную в стеке. Подсказка: попробуй на асме набросать этот вызов и посмотри на стек - то что какая то его область "неактивна" еще не значит что данные там самоустранились ;) Так что теоретически может прокатить, а на практике даже прокатит, см. gcc.

>Первый способ отнюдь не хитрый, а самый примитивный и медленный.

Про хитрость это ты начал :) Медленными бывают только алгоритмы а не средства языка. Память можно выделять заранее, и большим объемом, и т.д. Работает же ядро как-то :)

>Static- переменная в функции - это та же глобальная, облась видимость которой ограничена данной функцией.

Не бывает глобальных переменных с ограниченной областью видимости. Факт :) static указывает на то что переменная должна иметь размещение в памяти.

>Да я же говорил уже - это позволяет вернуть четыре символа за раз на регистре.

А в чем здесь ускорение то? С каких пор операция "вернуть int в регистре" быстрее чем "вернуть указатель на массив байт в регистре". Причем во втором случае можно вернуть сотни символов за раз. Вообще первое правило оптиизации - сначала найти что оптимизировать а потом оптимизируй :) Ведь возвращаемые данные потом, я так понимаю надо будет использовать (причем как, тоже становится ясно из обсуждения), вот где будет проблема а не в том чтобы вернуть :)

KIV
()

#include <stdio.h>
#include <inttypes.h>

int main() {
    uint32_t x = 0x31323334;
    printf("%c%c%c%c\n",
                ((char *)(&x))[0],
                ((char *)(&x))[1],
                ((char *)(&x))[2],
                ((char *)(&x))[3]);
    return 0;
}

Но вообще-то так делать не надо, потому что некрасиво и бессмысленно. 

  Во-первых, printf сама по себе функция небыстрая 
(ей, знаешь ли, парсить строку формата каждый раз надо). 
4 раза putc должно быть _намного_ быстрее, или, если совсем 
мелочно экономить, то write(filedesc, &x, 4);
главное, не перемешивать это дело с буферизованным вводом-выводом.
  Во-вторых, даже без учета этого любой ввод-вывод на 
много порядков дороже копирования 5-байтной строки.
  В-третьих, 2 миллиона строк - это смешное количество. Я лично писал 
статистическую программу для большого портала, которая прожевывает >10
миллионов строчек лога ежедневно, и потом генерит месячный отчет по 
>300 миллионам. И большая часть этой проги написана на Perl, 
парсер/конвертер логов - так целиком. И таки работает, с 
удовлетворительной скоростью.

  Мораль сей сказки была прекрасно сформулирована, если я не ошибаюсь, Кнутом: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil".

anonymous
()
Ответ на: комментарий от KIV

> Блин загнул то. "Фрейм" е-мое :)

Я вообще удивлён, что такой распространённый термин у кого-то вызывает
недоумение. Почитай что-нибудь по этому словосочетанию. Например:

http://en.wikipedia.org/wiki/Stack_frame

> так называемые "фитчи". 

Они же "хаки", они же "грязные методы". Их следует бояться как огня.

> если myfunc(x)возвращает указатель даже на переменную размещенную в
> стеке. Подсказка: попробуй на асме набросать этот вызов и посмотри на
> стек - то что какая то его область "неактивна" еще не значит что данные
> там самоустранились ;) Так что теоретически может прокатить, а на
> практике даже прокатит, см. gcc. 

Бред какой-то. То, что в твоём частном сулчае всё "прокатит", это
чистой воды случайность. На одной архитектуре прокатит, на другой
стек может быть организован совершенно по-другому. Да и даже в твоём
случае можно включить GCC'шную механику отслеживания переполнения
стека, что всё это "прокатывание" разломает в два счёта... Компилятор
может вставлять очистки неактивных фреймов. Так что описанная "фитча"
- это грязный, никуда не годный и крайне опасный хак.

> static указывает на то что переменная должна иметь размещение в
> памяти.

Гы, а где ж ей ещё находиться-то? :))

> С каких пор операция "вернуть int в регистре" быстрее чем "вернуть
> указатель на массив байт в регистре".

С таких, что во втором случае получается косвенная адресация в память,
а в первом память не участвует вообще.

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

Да всё это понятно, конечно. Просто афтару уж очень хотелось возвращать
именно ЧЕТЫРЕ символа :) И всё это не даст практически никакого ускорения,
как уже неоднократно было здесь сказано.

jek_
()
Ответ на: комментарий от jek_

> вообще удивлён, что такой распространённый термин у кого-то вызывает недоумение. Почитай что-нибудь по этому словосочетанию. Например: http://en.wikipedia.org/wiki/Stack_frame

ЗЫ. Это как-раз редирект с направильного термина на правильный "Call stack" :) Слово фрейм по англицки вообще означает "структура" :) И вообще из твоих слов выходило что для каждой функции какой то свой "фрейм".

>Они же "хаки", они же "грязные методы". Их следует бояться как огня.

Ага а еще goto - табу. Вообще проcто надо знать целевой процессор и нет проблем. А добиться высокой эффективности (а порой и высокая компактность кода нужна) без использования таких вот фитч невозможно. Пошукай коды ядра Linux, в директории arch там много интересного найдешь :)

>То, что в твоём частном сулчае всё "прокатит", это чистой воды случайность.

Это не в "моем" случае, а в случае описанном аффтаром :) И совсем не случайность а понимание арихитектуры. Ключевое слово конечно "понимание" :)

>Да и даже в твоём случае можно включить GCC'шную механику отслеживания переполнения стека, что всё это "прокатывание" разломает в два счёта...

Че сказал то понял? Мы тут блин, оптимизируем по скорости, а он проверки переполнения (а причем здесь вообще переполнение?) да очистку фреймов какихто. Опять "фреймы" в множественном числе, ты статью то которую привел здесь прочитай! Кстати, а что за фишка такая "очистка неактивных фреймов"? В области искусственного интеллекта я это еще понял бы, но здесь - в чем смысл и примеры в студию %))

>> static указывает на то что переменная должна иметь размещение в памяти.

>Гы, а где ж ей ещё находиться-то? :))

Автоматические переменные размещаются в стеке или в регистрах, вот где.

>С таких, что во втором случае получается косвенная адресация в память а в первом память не участвует вообще.

:):):) Лол! А прежде чем в твой инт записать данные, не надо их из памяти извлекать? Какая разница когда будет обращение к памяти, до возвращения, или после - оно все равно будет :) Только вот с интом одни проблемы: потом еще и распаковывать надо и плюс кэш толком не отрабатывает.

>Просто афтару уж очень хотелось возвращать именно ЧЕТЫРЕ символа :) И всё это не даст практически никакого ускорения, как уже неоднократно было здесь сказано.

А для чего споришь тогда? :):)

KIV
()
Ответ на: комментарий от MKuznetsov

>printf("%4s",&x);

printf("%.4s",&x);

так будет точнее

KIV
()
Ответ на: комментарий от KIV

> > вообще удивлён, что такой распространённый термин у кого-то вызывает недоумение. Почитай что-нибудь по этому словосочетанию. Например: http://en.wikipedia.org/wiki/Stack_frame

> ЗЫ. Это как-раз редирект с направильного термина на правильный "Call stack" :) Слово фрейм по англицки вообще означает "структура" :) И вообще из твоих слов выходило что для каждой функции какой то свой "фрейм".

Не с неправильного, а с более частного (stack frame не существует вне call stack). Цитата прямо из той статьи:

http://en.wikipedia.org/wiki/Stack_frame#Structure

A call stack is composed of stack frames (sometimes called activation records). Each stack frame corresponds to a call to a subroutine which has not yet terminated with a return.

Так что таки да, "каждой функции какой то свой "фрейм"" - область памяти от текущего указателя (верха) стека по направлению к его дну, в которой лежат параметры вызова, адрес возврата и автоматические переменные. А команда ret N, выполняемая при выходе из функции, перемещает указатель стека так, что со стека снимается ровно эта часть; ничто не мешает компилятору, скажем в целях безопасности, генерить код, затирающий содержимое стека после возврата.

anonymous
()
Ответ на: комментарий от KIV

> ЗЫ. Это как-раз редирект с направильного термина на правильный "Call
> stack" :) Слово фрейм по англицки вообще означает "структура" :)

Я так и знал, блин, я так и знал, что этот человек не сможет прочитать
статью дальше одного экрана :)) В данном случае frame переводится не
как "структура", а как "кадр", т.е. маленький кусочек стека, куда
фукнция может складывать свои временные переменные.

> Вообще проcто надо знать целевой процессор и нет проблем.

А что, афтар указал целевой процессор? Где?

> Это не в "моем" случае, а в случае описанном аффтаром :) И совсем не
> случайность а понимание арихитектуры.

Бред. Это как раз непонимание архитектуры. И собственно архитектура
тут не причём. Важно здесь поведение компилятора. Ты не можешь знать,
что там компилятор делает со стеком. Он ЗАПРОСТО может вставить какую-
нибудь очистку его или иную запись в произвольные фреймы.

> Че сказал то понял? Мы тут блин, оптимизируем по скорости, а он
> проверки переполнения (а причем здесь вообще переполнение?) да
> очистку фреймов какихто.

Я-то понял. А где афтар указал ключи компилятора, его версию, версию
операционки, название архитектуры? Из вопроса следует _только_, что
sizeof(int) == 4 * sizeof(char). И это всё. А вот из-за таких супчиков,
которые не понимают, что процессоры бывают разные, что стеки тоже
бывают разные, и что компилятор может творить что хочет, - вот из-за
них-то и вылазят потом дыры в том же ядре линукса, да и вообще 
повсеместно.

> Автоматические переменные размещаются в стеке или в регистрах, вот
> где.

А стек это случайно не память?

> :):):) Лол! А прежде чем в твой инт записать данные, не надо их из
> памяти извлекать? Какая разница когда будет обращение к памяти, до
> возвращения, или после - оно все равно будет :)

Из чего следует, что любая запись и чтение с регистра в общем случае
равнозначны по производительности аналогичной записи/чтению косвенно
из памяти. Потому что данные всё равно когда-то нужно считать/записать
в память/из памяти :) Да, батенька... на эту тему я больше с вами 
говорить не буду, ибо тут всё ясно.

> А для чего споришь тогда? :):)

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

jek_
()
Ответ на: комментарий от jek_

>Я так и знал, блин, я так и знал, что этот человек не сможет прочитать статью дальше одного экрана :)) В данном случае frame переводится не как "структура", а как "кадр", т.е. маленький кусочек стека, куда фукнция может складывать свои временные переменные.

lol! Ты сам то ее читал, там всего 2 экрана и на втором раздел "Use"? :)

>А что, афтар указал целевой процессор? Где?

Видимо это освобождает от знания целевой платформы вообще, и запрещает использовать ее особенностей в частности :)

>Ты не можешь знать,что там компилятор делает со стеком. Он ЗАПРОСТО может вставить какую-нибудь очистку его или иную запись в произвольные фреймы.

Все ясно. Просто твой опыт оптимизации ограничивается ключами компилятора -O* :) Снова тихо офигеваю от "очистки и записи в ПРОИЗВОЛЬНЫЕ фреймы" :) Вы, деточка, как со стеком работают слышали?

>И собственно архитектура тут не причём.

А нах она вообще кому сдалась :):):)

>Я-то понял. А где афтар указал ключи компилятора, его версию, версию операционки, название архитектуры? Из вопроса следует _только_, что sizeof(int) == 4 * sizeof(char). И это всё.

Это что ответ на вопрос о целесообразности гениально предложенного вами использования механизмов контроля переполнения стека и очистки стека в программе требующей оптимизации по скорости исполнения? :)

>А вот из-за таких супчиков,которые не понимают, что процессоры бывают разные, что стеки тоже бывают разные, и что компилятор может творить что хочет, - вот из-за них-то и вылазят потом дыры в том же ядре линукса, да и вообще повсеместно.

и несколькими строками ниже

>А стек это случайно не память?

Мде :) Сам с собой что-ли разговариваешь ? Согласен со вторым тобой : "стеки тоже бывают разные", смотри форт процессоры :) А насчет взбесившихся компиляторов... это без комментариев, действительно страшная вещь :)

>Из чего следует, что любая запись и чтение с регистра в общем случае равнозначны по производительности аналогичной записи/чтению косвенно из памяти. Потому что данные всё равно когда-то нужно считать/записать в память/из памяти :) Да, батенька... на эту тему я больше с вами говорить не буду, ибо тут всё ясно.

Читать вроде умеем а думать похоже еще нет :) Вы знаете какой-то волшебный способ перемещения данных в регистры :)? Из этого следует что в регистрах нефиг "хранить" данные и катать их по всей программе из функции в функцию:) Регистры общего назначения предназначены для кратковременного хранения, а вы как я понял предлагаете прокачать "(~2млн) записей" через eax исключительно с целью организации "быстрго" возврата данных одной единственной функцией:) Вот где бред то! Детка, почитайте что-нибудь по оптимизации на досуге, обязательно, Касперского например! :)

>Это ты вылез и начал спорить.

Не знаю как и назвать :) Детский маразм? Посмотри еще разок тему - кто там и куда вылез :)

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

Опять :) Я этого никому не советовал, это ты сам додумал :) То что ты недогоняешь что подпрограммы могут возвращать указатели это уже не моя проблема :)

Всем сорри за оффтоп.

ЗЫ. Просто если чето с первого прочтения не догнал, прочитай еще раз и обязательно подумай :)

KIV
()
Ответ на: комментарий от KIV

Да, в общем, я вижу, что дискуссия выродилась в сплошной рёв, крики и
оскорбления обиженного ребёнка. Т.к. этот ребёнок не способен сказать
что-либо конструктивное, не вижу смысла продолжать разжигать это 
представление.

jek_
()
Ответ на: комментарий от anonymous

>>Это как-раз редирект с направильного термина на правильный "Call stack" :) Слово фрейм по англицки вообще означает "структура" :) И вообще из твоих слов выходило что для каждой функции какой то свой "фрейм".

Да, здесь я не совсем ясно выразился. Хотя, в принципе, из контекста спора можно понять, что меня заинтересовало понятие "фрейм стека" именно как сущности, которая по мнению уважаемого jek_ будучи неактивной может потерять свои значения, цитата:

>>А ничего, что фрейм стека myfunc()уже не активен и там может быть что угодно, мусор? Что, это пустяки?"

В принципе, то что подразумевается в этой статье и в статье http://en.wikipedia.org/wiki/Stack_%28data_structure%29 (тут даже с картинками для непонятливых :)) под понятием "фрейм стека", будучи неактивным, не теряет данных, не забивается мусором, и уж тем более не должен очищаться.

Более того пользуясь даже вашим, уважаемый anonymous :), определением "фрейма стека" как "область памяти от текущего указателя (верха) стека по направлению к его дну, в которой лежат параметры вызова, адрес возврата и автоматические переменные." можно понять что после выхода из функции ее "фрейм стека", фреймом стека уже не является :), так как лежит вне границ [верх стека, дно стека]. На лицо путаница в терминологии, на что я и указал уважаемому jek_. :)

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

Как это ничто не мешает. Вы должны мешать. Особенно если хотите добиться оптимального времени исполнения.

Правда у меня есть еще вопрос: какие компиляторы вы встречали которые генерят код затирающий содержимое стека?

На микроахритектурном уровне это можно безболезненно сделать - после выборки из стека забивать ячейку (да и то если стек не в специальной памяти, только ячейку которая лежит в кэше и если кэш не сбрасывается принудитьльн по записи в память). А вот чтоб компилятор такую бяку, да еще и по умолчанию!!! Такое разве живет где-нибудь?

ЗЫ. А еще, если говорить про выборочный доступ к "произвольному фрейму" стека мне вообще непонятно причем здесь понятие "стек". Объясните плиз.

KIV
()
Ответ на: комментарий от jek_

>Да, в общем, я вижу, что дискуссия выродилась в сплошной рёв, крики и оскорбления обиженного ребёнка. Т.к. этот ребёнок не способен сказать что-либо конструктивное, не вижу смысла продолжать разжигать это представление.

Я не ребенок. Извини если обидел, я не хотел. Очень жать что время потраченое на тебя пропало за зря. В будущем если начинаеш переходить на личности ожидай что тебе ответят втом же духе.

KIV
()
Ответ на: комментарий от KIV

> В принципе, то что подразумевается в этой статье и в статье http://en.wikipedia.org/wiki/Stack_%28data_structure%29 (тут даже с картинками для непонятливых :)) под понятием "фрейм стека", будучи неактивным, не теряет данных, не забивается мусором, и уж тем более не должен очищаться.

Доступ к кадру (в т.ч. по указателям на автоматические переменные) после выхода функции-владельца влечет неопределенное поведение. Т.е. оно может работать, может падать с ошибкой защиты, а может случиться, что "green demons will fly out of your nose" (C). Короче, так делать нельзя.

> можно понять что после выхода из функции ее "фрейм стека", фреймом стека уже не является :), так как лежит вне границ [верх стека, дно стека].

Вот именно. Все, что не лежит в границах выделенных сегментов - табу. И да, все что выше (ну, на i386 - ниже, ибо он растет "навстречу") указателя стека - это не стек. В самом простом случае, ядро спокойно может удалить маппинг соответсвующих страниц, и выдывать новые-пустые при формировании новых кадров (т.е. следующих вызовах функций).

> Как это ничто не мешает. Вы должны мешать. Особенно если хотите добиться оптимального времени исполнения.

Если бы мне так уж нужно было заниматься микрооптимизацией - я купил бы книжку про ассемблер (но, поверь, за пределами написания драйверов/программ для микроконтроллеров, ассемблер используют только фанаты, и почти все - не в рабочее время. Ну матбиблиотеки еще пишут, и то не все). А если ты пишешь на ЯВУ - будь добр следовать его спецификации.

> А вот чтоб компилятор такую бяку, да еще и по умолчанию!!! Такое разве живет где-нибудь?

Не знаю, но подозреваю, что бывает, во всяких "trusted" системах, где опциональные защитные функции включены "из коробки".

> ЗЫ. А еще, если говорить про выборочный доступ к "произвольному фрейму" стека мне вообще непонятно причем здесь понятие "стек". Объясните плиз.

Вообще говоря, произвольным доступом к стеку вызовов (если мы говорим о С) может заниматься только если отладчик. А про "понятие стек" - про инкапсуляцию ты слышал?

Короче, я надеюсь, что ты не программист, а просто мелкий зануда. Ибо компания, взявшая такое на работу - ССЗБ. Если студент - читай книжки, оне рулез. А то чего мы тут тебя бестплатно учим-то?

anonymous
()
Ответ на: комментарий от anonymous

> Ибо компания, взявшая такое на работу - ССЗБ. Если студент - читай
> книжки, оне рулез. А то чего мы тут тебя бестплатно учим-то?

> anonymous (*) (28.06.2006 22:41:11)

Respect!

jek_
()
Ответ на: комментарий от anonymous

Слушй, anonymous, ничтожное проявление великого НИЧТО, ты вообще читаешь прежде чем встрять?

Вот с этого места прочитай несколько раз, может дойдет: - с чего ты взял что я кому то предлагаю использовать автоматические переменные вне функции в которой они выделены? С чего ты взял что я сказал что если это гдето и возможно то это безопасно? Ты вообще откуда такой вылез? (Или тебя с пониманием сложно подчиненных предложений проблемы?) - посмотри что такое на самом деле "неактивный фрейм" (для дубов вроде тебя на картинке в статье на wikipedia). Разумей наконец что данные из него ничем не должны затераться, дуб блин стоеросовый.

>Если бы мне так уж нужно было заниматься микрооптимизацией - я купил бы книжку про ассемблер.

А я бы скачал мануалы по целевой платформе, только имбицилы занимаются оптимизацией на учебнику ассемблера.

>(но, поверь, за пределами написания драйверов/программ для микроконтроллеров, ассемблер используют только фанаты, и почти все - не в рабочее время. Ну матбиблиотеки еще пишут, и то не все).

Абалдеть :) Ты типа хочешь сказать что асемблер это ничтожная доля на рынке ПО? Ты хоть знаешь каково соотношение числа микроконтроллеров и процессоров общего назнначения в штуках в мире? А знаешь что даже моделей микроконтроллеров не на один на порядок больше чем моделей настольных процессоров :) А знаешь сколько handmade процессоров собрано на HDL со своими сисетмами команд? Ты наверное еще думаешь что фирмваре твоей видюхи оптимизировано компилятором с ключиком -O %) lol-ка ты!

>А если ты пишешь на ЯВУ - будь добр следовать его спецификации.

Разве с спецификации на С где-то что то сказано про то что следует очищать стек?

>Не знаю, но подозреваю, что бывает, во всяких "trusted" системах, где опциональные защитные функции включены "из коробки".

Я вот подозреваю, что если в чем то не уверен надо писать IMHO. И вообще не разеветь ротик пока не знаешь о чем речь. Намек ясен?

>> ЗЫ. А еще, если говорить про выборочный доступ к "произвольному фрейму" стека мне вообще непонятно причем здесь понятие "стек". Объясните плиз. Вообще говоря, произвольным доступом к стеку вызовов (если мы говорим о С) может заниматься только если отладчик. А про "понятие стек" - про инкапсуляцию ты слышал?

Если бы ты внимально читал тред (но это не в твоих правилах, я знаю) то понял бы что этот вопрос надо задавать jek_у. Здесь твое пустобрехство пропало задаром.

>Короче, я надеюсь, что ты не программист, а просто мелкий зануда. Ибо компания, взявшая такое на работу - ССЗБ.

Я не программист, я ведущий программист :) А компания процветает, не без моей помощи.

>Если студент - читай книжки, оне рулез. А то чего мы тут тебя бестплатно учим-то?

Советую самому поучиться, хотябы вести беседу на форуме :)

KIV
()
Ответ на: комментарий от anonymous

Все закругляюсь, тяжело вести беседы с глухими, у которых на уме только желание хорошо "выглядеть" на форуме :( Не одного толкового предложения по теме треда, только нападки, продиктованные желанием выделиться на фоне другого человека :(

ЗЫ. И вообще есть подозрения что тайна великого anonymousa раскрыта :) Уж больно он на jeka смахивает тормозом своим :)

KIV
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.