LINUX.ORG.RU

> Но пацаны хотят писать char m[] = "Preved krosavcheg"; и не иметь нулевого байта после 'g'.

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

char m[17] = "Preved krosavcheg";

сэкономит этот байт..

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

dilmah

Супер, не знал, спасибо.

Но у реальных пацанов зачастую мильён строчек, уже записанных без указания размера в квадратных скобках. Тут либо исходнико-модифицирующий-символьносчитающий скрипт писать, который в скобки размеры повставляет, либо искать компилер, который умеет опцию типа --no-null-finalize.

irc_007_1
() автор топика

Ты хочешь странного.

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

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

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

>char m[17] = "Preved krosavcheg";

>сэкономит этот байт..

Ничего это не сэкономит - gcc в конце все равно ноль допишет. Чтобы небыло споров левых - посмотри биннарник в hex-редакторе после сборки. А когда данные будут загружены в память при исполнении - там все равно до границы двойного слова будет все нолями забито.

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

> Ничего это не сэкономит - gcc в конце все равно ноль допишет.

$ cat tst.c
char a[3] = "abc";
char b[3] = "def";
char c[3] = "ghi";

main()
{
  return 0;
}
$ gcc tst.c
$ od -c a.out | grep -A1 'a *b *c'
0002540  \0  \0  \0  \0  \0  \0  \0  \0   x 224 004  \b   a   b   c   d
0002560   e   f   g   h   i  \0  \0  \0  \0   G   C   C   :       (   G

abcdefghi идут слитно, без нулей

Впрочем это не важно.

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

> Можно поподробнее, как они используются?

Очевидно CHARS(m, "Preved krosavcheg")

dilmah ★★★★★
()

Топикстартеру: то что ты хочешь сделать либо глупо либо нестандартно.

Обрати внимание на такую фичу:

"Preved "
"Krosavcheg"

это то же самое что "Preved Krosavcheg" -- то есть строки конкатенируются компилятором.

dilmah ★★★★★
()

Паскаль возьми. Или классический Форт. Там вместо asciiz используются счётные строки. Не нулевой байт в конце, а длина строки - вначале :) В SP-Forth, правда, для совместимости с C-based, в строках используются оба решения. В начале - длина строки, в конце - нулевой байт :)

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

извратиться-то можно. gcc -S и править ассемблерный исходник скриптом на perl/sed, убрать 0 байт. Но не нужно. А нужно нормальные строки брать, в паскаль-стиле или что-то подобное (можно придумать "менеджер ресурсов", который по содержимому ресурсов - строкам будет делать хеш, и адресовать всё по этому хешу, вместо строк в исходниках использовать константы-ключи в хеше). Использовать другие-не-С строки, иметь геморрой с конвертированием туда-сюда (в ОС-libc и asciiz) (можно правда, совместить с длиной asciz, сделать как PChar в паскале).

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

Ну вот, сейчас он возьмет паскаль, а потом появится тема - "как отпилить два байта от начала строки".

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

>$ cat tst.c
>char a[3] = "abc";
>char b[3] = "def";
>char c[3] = "ghi";

>main()
>{
> return 0;
>}
>$ gcc tst.c
>$ od -c a.out | grep -A1 'a *b *c'
>0002540 \0 \0 \0 \0 \0 \0 \0 \0 x 224 004 \b a b c d
>0002560 e f g h i \0 \0 \0 \0 G C C : ( G

>abcdefghi идут слитно, без нулей

>Впрочем это не важно.

Для кого-то видимо важно раз создал топик :) Для глобальных переменных да - он не дописывает ничего. Для локальных объявленных внутри ф-ции дописывает всегда.

bash-3.2$ cat tst.c
int main()
{
char a[4] = "abcd";
char b[4] = "efgh";
char c[4] = "iklm";

return 0;
}

bash-3.2$ od -c a.out | grep -A1 'a *b *c'
0002020 a b c d \0 e f g h \0 i k l m \0 \0
0002040 \0 \0 \0 \0 377 377 377 377 \0 \0 \0 \0 377 377 377 377

Для наглядности массивы сделал 4 байтными, чтобы было ясно что это не выравнивание на границе двойного слова.

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

> Для кого-то видимо важно раз создал топик :)

когда он наконец объяснит какую проблему он этим хочет решить, то я чую ему будут давать совсем другие советы:)

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

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

Опять таки непонятно какую проблему чел хочет решить, а от этого много зависит.

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

>Опять таки непонятно какую проблему чел хочет решить, а от этого много зависит.

Согласен - для однозначного решения задачи это надо на асме писать :) И вообще эконмить байт в то время когда уже 64 битные процессоры входу - маразм. Например параметры даже в пользовательских ф-ях все равно будут передаваться через стек в соответствии с максимальной разрядностью регистров процессора.

anonymous
()

Интересная идея. Жалко не совместимая с С90.
Но ты не бросай её, напиши компилятор для своего языка с-0 (c без нулей).
Ещё можно убрать выравнивание в структурах и других данных - оно тоже много место отъедает.
Я думаю null terminated strings - это заговор со стороны производителей жёстких дисков.

P.S. Уже без шуток: оптимизация в малом - корень всех зол.

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

Уточню-ка я вопрос.

Есть много исходников со строками типа

...

char str_67[] = "ZEBRA CHICAGO";

char str_68[] = "ZEBRING STACK";

char str_69[] = "ZEBRUSSIMO 01";


То есть это куча строк, к которым в коде автор обращается по символическим именам str_67, str_68 и т.п. Все они одинаковой длины. Об этой длине знает код. Коду даже плевать, что будет после каждой строки - ноль или не ноль или другие полезные данные. Просто потому, что код никогда дальше длины не заглядывает.

И на этой почве автору обидно, что на тыщу строк компайлер кладёт ему ещё тыщу нулей. Автор обидчивый конечно, зараза, тоже. Забил бы на всё болта, дак ведь нет, он собака зануда попался. Ну это уже не поменять, он таким уродился и здесь вопросы понятны: "когда же он уже коньки отбросит, гад". Но всё это потом, а в данный момент...

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

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

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

> - char str_67[] = "ZEBRA CHICAGO";
> + char str_67[] = {'Z', 'E', 'B', 'R', 'A', ' ', 'C', 'H', 'I', 'C',
> 'A', 'G', 'O'};

Тут добавляется задача конвертирования исходников.

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

> Препроцессор на перле неспешно пишется за полчаса.

Ещё бы конечно было указано, кем.

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

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

Не хотел обидеть словом маразм - это относилось не к конкретному человеку - а вообще к идее экономить байты. Как ты уже понял тривиально задачу твою сменой компилятора не решить, в любом случае нужно править код, а советов было уже минимум два. Еще осмелюсь предложить подумать - так ли тебе это нужно - если код инициализации по размеру больше чем те 1000 байт которые ты хочешь сэкономить.

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


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

Откуда известно, что я уже что-то понял? Нет, я ничего не понял, я продолжаю верить и ждать!
Историю про код инициализации не просёк. Код инициализации был и будет быть, а нули можно и похерить.

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

> char str_67[] = "ZEBRA CHICAGO";

выше определили макро CHARS

прогоняешь исходники через обработку:

cat file.c | sed 's/char[ \t]*\([a-zA-Z_0-9]*\)\[[ \t]*\][ \t]*=[ \t]*\(".*"\)[ \t]*;/CHARS(\1, \2);/'

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

>Историю про код инициализации не просёк.

Это я к тому что пиши на асме - там нет кода инициализации и строки без нулей будут.

>Нет, я ничего не понял, я продолжаю верить и ждать!

Хочешь усилием воли заставить появиться компилятор под твою задачу ?

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

> если код инициализации по размеру больше чем

я так понял, что данные глобальные -- то есть кода инициализации нет.

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

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

int main()
{
return 0;
}

Даже с флагом -Os бинарник будет болше 2 килобайт.

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

> Код инициализации есть всегда

это O(1)

А нулей в строках O(кол-во строк).

dilmah ★★★★★
()

А пацаны в курсе - что когда они это сделают (даже если они напишут в виде массива ['P', 'r', 'e', ...] - все сишные функции работы со строками сразу перестанут работать?

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

> А пацаны в курсе

выше писали:

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

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

char str_67[] = "ZEBRA CHICAGO";

char str_68[] = "ZEBRING STACK";

char str_69[] = "ZEBRUSSIMO 01";

за такой код раньше отрывали руки :) а вообще

char str="ZEBRA CHICAGO" "ZEBRING STACK" "ZEBRUSSIMO 01"; enum str_index={ s67=0,s68=13,s69=26,.. };

при -O2 обращение str[s67] по всем параметрам идентично вашему str_67 и пресловутых нулей нет..хотя кривизны подхода это не меняет :)

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

> char str="ZEBRA CHICAGO" "ZEBRING STACK" "ZEBRUSSIMO 01";

тут ошибка.

А идея с конкатенацией предлагалась выше.

dilmah ★★★★★
()

слей строки в файл сплошняком и слинкуй как блок данных. Обращаться к n-ной строке можно как str [n*len].

Ещё можно пропустить скомпиленый бинарник через sed s/\000//g . Возможно, работать он после этого не будет, но судя по сложности обсуждаемых здесь задач, это вряд ли кто-нибудь заметит.

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