LINUX.ORG.RU

динамические строки Си. Реинкарнация

 


0

2

Сегодня залил в реп первую версию библиотеки для работы с динамическими строками на Си: https://github.com/maksspace/dynamic-string

Товарищи, посмотрите это творение и выскажете свое мнение об этом) Буду очень признателен за конструктивную критику.)

Мои рекомендации по API:

1. Разделить строки на мутабельные и иммутабельные. Иммутабельные хранить как посоветовал waker, помимо прочего capacity им не нужен. В C перегрузки нет и наследования тоже, как можно грамотно оформить общее API — я даже не знаю. В крайнем случае продублировать все функции. В иммутабельных строках длину хранить до указателя. Это позволит передавать такой указатель сразу в любую функцию без доп вызовов, очень удобно. Конечно хранить с нуль-терминатором.

2. Изначально сделать поддержку юникода. Поддержку индексации по символу убрать, это вредная операция. Можешь изучить стандартную библиотеку в Rust или Swift для вдохновения, там это сделано правильно. При этом поддержка юникода требует специальных либ, что не всем надо, так что сделай это опциональным. Какой-нибудь парсинг UTF-8 пусть будет встроенный, а вот всякие toUpperCase это уже опционально, пусть программист сам выбирает, надо ему это или нет.

3. Сделать отдельный класс — массив байтов. Сделать удобный конструктор для mmap-а, для перевода строки туда-назад и тд.

4. Сделать удобные композируемые потоки. Можно вдохновиться Джавой или тем же Rust-ом.

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

Херня, достаточно одного маллока.

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

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

Что возвращает нас к локали и недетерминированности ловера

Я зашел разъяснить безграмотным оболтусам вроде тебя, что для регистро-независимого поиска используется не lowercase (который действительно очень сильно зависит от локали), а нормализация + casefolding, единственными тонкими местами которых является турецкая локаль, в остальном — полная локаленезависимость.

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

А ты, стало быть, из тех, кто для любых счетчиков всегда берет intmax_t? Даже затрудняюсь сказать, какая из двух каст более ущербна.

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

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

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

Зато size_t стопудово на всех машинах один и тот же. А то запилишь ты, скажем, uint в надежде, что получится 32 бита, а где-нибудь этот самый uint восьмибитный. И превед, строки, длинней 255 символов...

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

Потому что мне еще ни разу в жизни не требовались строки больше 4Gb.

И поэтому в библиотеке общего назначения нужно захардкодить ограничение в 4 GB.

i-rinat ★★★★★
()
Ответ на: комментарий от Eddy_Em

Зато size_t стопудово на всех машинах один и тот же.

Разве? А я думал, что такой же ширины, что и машинное слово.

i-rinat ★★★★★
()
Ответ на: комментарий от Eddy_Em

Зато size_t стопудово на всех машинах один и тот же.

наоборот:

$ echo '#include <stdio.h>
int main() {
printf ("%ld\n", sizeof (size_t));
return 0;
}' | gcc -x c -
$ ./a.out 
8
$ uname -m
x86_64
waker ★★★★★
()
Ответ на: комментарий от Legioner

Чувак, не дави интеллектом. Человек, наверное, свою первую программу написал.

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

size_t стопудово на всех машинах один и тот же

а где-нибудь этот самый uint восьмибитный

Читай стандарты! А, это Эдди...

anonymous
()

Тред не читал, могу сбаянить.

Нет функции получения char const* этой строки, поэтому твою строку практически нереально где-то использовать.

Features:
Data of dynamic string are stored without of terminator '\0'

Фичи – это какой-то профит для пользователя. Вот это вот – деталь реализации, а не фича. И это плохое решение, ты как бы сэкономил байт, но в реальной жизни получение обычной си строки будет очень частой операцией, поэтому лучше таки хранить этот несчастный нолик. Я как-то давно тоже велосипедил подобные штуки-дрюки и прошел через такую «фичу» :)

staseg ★★★★★
()
Последнее исправление: staseg (всего исправлений: 1)

О божечки, я тут копнул. И что я нашел. Что я нашел - золотую жилу.

Я тут попытался сделать анализ твоего гуана - меня хватило на 20-30% - дальше жопа уже не выдерживала. http://pastebin.com/d3vtFPYA

Товарищи, посмотрите это творение и выскажете свое мнение об этом) Буду очень признателен за конструктивную критику.)

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

Сегодня залил в реп первую версию библиотеки для работы с динамическими строками на Си

Оно итак есть - оно не нужно. Слишком дерьмо.

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

Совсем обнаглели пока меня не было.

Разделить строки на мутабельные и иммутабельные.

Зачем?

В C перегрузки нет и наследования тоже, как можно грамотно оформить общее API — я даже не знаю.

Зачем?

В иммутабельных строках длину хранить до указателя.

Хорошо.

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

Щито?

Изначально сделать поддержку юникода.

Зачем? Она итак есть в обычных чарах.

Поддержку индексации по символу убрать, это вредная операция.

Это и называется «поддержка юникода, вернее утф8». С чего это вредная операция?

Можешь изучить стандартную библиотеку в Rust или Swift для вдохновения, там это сделано правильно.

Мочаговна.

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

Каких таких либ?

Какой-нибудь парсинг UTF-8 пусть будет встроенный

Зачем он нужен?

Проблема ламерков в том, что они не понимают, что утф8 - это протокол хранения и транспортировки и во внутреннем представлении, при обработке - присутствовать не должен.

У более-менее вменяемых людей юникод хранится в утф16/32, а у нормальных в собственных таблицах. После чего все проблемы модные у ламерков уходят.

toUpperCase

Ну какбэ да - 100% нужна либа.

3. Сделать отдельный класс — массив байтов. Сделать удобный конструктор для mmap-а, для перевода строки туда-назад и тд.

Си.

4. Сделать удобные композируемые потоки. Можно вдохновиться Джавой или тем же Rust-ом

О боже. Жавапотоки-то они такие. Легендарные.

Зачем великие жабка-эксперты пишущие лабу на крестах появляются в сишкатредах? Меня посмешить?

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

Ты предлагаешь использовать undefined behavior.

Очередной эксперт.

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

Ведь при UB можно делать что угодно.

Нет, проблема в том, что ты нулёвый. Как и адепт, которому ты отвечаешь - для этого есть:

struct { data[0]; };

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

Ахах) Я не понимаю одного - нафига писать «это не правильно» и больше ничего не говорить)? почему не так, как сделать лучше ... ничего из этого. а очень хотелось бы

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

И не убогой макулатуре.

Окей, какую макулатуру считаешь не убогой? Что стоит читать?

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

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

int table[4];
bool exists_in_table(int v)
{
    for (int i = 0; i <= 4; i++) {
        if (table[i] == v) return true;
    }
    return false;
}

int main()
{
    table[0] = 0;
    table[1] = 1;
    table[2] = 2;
    table[3] = 3;

    cout << "10 in table " << exists_in_table(10);
}

при оптимизации возвращает истину.

Или

enum {N = 32};
int a[N], pfx[N];
void prefix_sum (void)
{
  int i, accum;
  for (i = 0, accum = a[0]; i < N; i++, accum += a[i])
    pfx[i] = accum;
}

компилируется gcc в бесконечный цикл, так как происходит доступ к a, то при i > 31 будет UB => i или меньше 32 или UB => проверку i < N можно выкинуть, так как это всегда истина.

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

struct { data[0]; };

Тогда уж struct { size_t length; size_t capacity; char data []; }

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

Почитай http://habrahabr.ru/post/229963/

Выводы просто фееричны.

Код с UB успешно выпиливается и gcc

Не код с уб, а именно этот код с уб. Это не return true; как пишут балаболы - это какая-то неведомая, ошибочная, алогичная логика. Я пол часа уже сижу и думаю исходя из какой логики гцц выпиливает именно этот код.

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

Но вот каким образом удаление итерацией позволило ему заменить последнюю итерацию на выполнение условия с предыдущей итерации - загадка.

и (ещё больше) clang.

Со шлангом это не работает.

Хочешь сказать, что их никто не использует?

Во всех остальных примерах ничего не логичного нет.

int main() {
  int *p = (int*)malloc(sizeof(int));
  int *q = (int*)realloc(p, sizeof(int));
  *p = 1;
  *q = 2;
  if (p == q)
    printf("%d %d\n", *p, *q);
}

Тут должно быть в любом днище-конпеляторе 1 и 2. Это абсолютно логично и реалок тут не причём, как и уб.

  int *p = (int*)malloc(sizeof(int));
  int *q = (int*)realloc(p, sizeof(int));

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

А вот гцц, который знает об реалоке выводит: 2, 2, что верно.

  unsigned int i = 0;
  do {
    i+=2;
  } while (0==(i&1));

Этот и иные днищепримеры не имеют никакого отношения к бесконечным циклам. Это оптимизация выражений с константами.

Как так? Цикл завершится по return 1; — компилятор смог доказать, что теорема Ферма неверна?!

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

Иначе говоря, единственная возможность написать на C++ такой бесконечный цикл, который компилятор не смог бы удалить — это добавить внутрь цикла изменение внешнего состояния. Самый простой (и стандартный!) способ сделать это — изменять переменную, объявленную как volatile.

Нет, опять подмена понятий и убогость.

Бесконечный цикл не имеет смысла - то, о чём кукарекает балабол - это не бесконечные циклы - то циклы с выходом. Тут дело в потере управления, как и кукарекал выше про деление на ноль.

Конпелятор находит именно бесконечный цикл без каких-либо побочных эффектов - это не имеет смысла - это выпиливается.

Любой код будет работать, который будет иметь управляемый, либо недоступный для конпелятора выход. Цикл выпиливается только по причине, что конпелятор доказал его бесконечность, т.е. доказал отсутствие выходов из него.

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

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

при оптимизации возвращает истину.

Про это я писал. Теперь сделай:

int table[4];
bool exists_in_table(int v)
{
    for (int i = 4; i <= 8; i++) {
        if (table[i] == v) return true;
    }
    return false;
}

Это какой-то аллгичный баг, либо логика которой я не понимаю. На основании чего она происходит мне не ведомо. Она происходит только с перехода валидного индекса в невалидный, в цикле именно счётчиком, причём только в условии, при этом только на выполнение предыдущего условиия, вернее его тела.

компилируется gcc в бесконечный цикл

Нет, тут не может быть никакого бесконечного цикла. С чего ему там быть:

int i, accum;
  for (i = 0, accum = a[0]; i < N; i++, accum += a[i])
    pfx[i] = accum;
//равно
  for (i = 0/*, accum = a[0]*/; i < N; i++/*, accum += a[i]*/)
    /*pfx[i] = accum*/;

так как происходит доступ к a, то при i > 31 будет UB => i или меньше 32 или UB => проверку i < N можно выкинуть, так как это всегда истина.

Куллстори. Почему все нули такие смешные - какой жопой ты решил, что если уб - можно что-то выкидывать?

Ну выкинул ты обращение к а[32] и? Как это повлияло на цикл? Лисп мозг совсем атрофирует что-ли?

Логика пацанов просто ахренительна - каждый раз удивляюсь.

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

Ахах) Я не понимаю одного - нафига писать «это не правильно» и больше ничего не говорить)?

Это пишется для того, что бы ты аргументировал свои решения. Напиши - почему ты написал именно так.

Тебе сказали говно - не согласен/хочешь понять как - аргументируй свои решения. Пацан тебе пояснит как и почему это дерьмо и как «надо», либо сам обосрётся.

почему не так, как сделать лучше ... ничего из этого. а очень хотелось бы

Весь лор изпестрён моими «как сделать лучше», только лучше пока никто не осилил.

Основная проблема всего этого днища - это самая идея. С чего ты решил, что это нужно - это актуально? Что ты хочешь писать - реальный, рабочий код, либо дырявое легаси говно под убогое дерьмо.

В реальном коде никаких «динамических» и не динамических убожеств не требуется - это всё реализовано на уровне ОС и железа.

Память сама увеличивается - у неё там же есть длинна и капасити и она так же растёт без твоих днищ, сама.

#include<sys/mman.h>
#include<sys/unistd.h>
#include<fcntl.h>

enum {KB = 1024, MB = 1024 * KB, GB = MB * 1024ul};

uint64_t total_ram_size = 32ul * GB;//атрибутконструктор и как получить эту константу я уже писал

char * get_infinity_string(void) {
  return mmap(0, total_ram_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
}

void reset_capacity(char * str, uint64_t new_capacity) {
  if(new_capacity > total_ram_size) exit(1);
  madvise(str + new_capacity, total_ram_size - new_capacity, MADV_DONTNEED);
}

double get_rss(void) {
  int file = open("/proc/self/statm", O_RDONLY);
  char str[1024];
  read(file, str, 1024);
  return (atoll(strchr(str, ' ') + 1) * 4096.) / MB;
}

void free_string(char * str) {munmap(str, total_ram_size);}

void cleanup_free_string(char ** str) {free_string(*str);}

#define aka_cpp_string __attribute__((cleanup(cleanup_free_string))) char *
int main(void) {
  {
    aka_cpp_string str = get_infinity_string();
    fprintf(stderr, "%fMB\n", get_rss());
    memset(str, 0, MB * 100);
    fprintf(stderr, "%fMB\n", get_rss());
    memset(str, 0, GB);
    fprintf(stderr, "%fMB\n", get_rss());
    reset_capacity(str, MB * 500);
    fprintf(stderr, "%fMB\n", get_rss());
    reset_capacity(str, MB * 100);
    fprintf(stderr, "%fMB\n", get_rss());
  }
  fprintf(stderr, "%fMB\n", get_rss());
}

Всё, никаких переполнений, никаких заморочек + типа модный у пацанов автофри.

А то, чем занят ты - это не для сишки. Зачем ты пытаешься сделать то, что проще и лучше сделать на крестах? Сишка она про конкретный и иллитный код, а не про кулл апи в либах для жабистах.

Собственно больше твои строки ничего не умеют.

Рассказывай что ты хочешь и защищай свою реализацию.

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

Вот откуда - https://github.com/jasonmaclafferty/String/blob/master/libString/String.h. Просто решил поискать как это кто то делал раньше) потом я нашел это - https://github.com/antirez/sds - там такая структура не используется. но я пока не смотрел что там и как работает.

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

Вообщем, я хочу написать для себя интерпритатор языка, для практики, с синтаксисом:

` def summ arg1 arg2 ... argN : arg1*arg2* ... *argN возвращается результат этого выражения. def a summ 14 13 Операторы + - * / % || && > < <= >= == ! ` Если результат выражение не используется то результат пишется stdout.

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

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

Нет, тут не может быть никакого бесконечного цикла

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53265

если уб - можно что-то выкидывать

Если UB, то можно делать что угодно. В частности, можно считать, что в этом случае происходит переход на начало цикла без проверки.

Поэтому статически анализ показывает, что либо i < N, либо есть доступ к a, а значит можно делать что угодно. Значит всегда (по результату статического анализа) i<N.

Со шлангом это не работает.

Пример для шланга:

struct timeval tv;
unsigned long junk;
 	
gettimeofday(&tv, NULL);
srand((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);

Компилируется в srand(0)

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от PotentialCppTsar

Это не return true; как пишут балаболы - это какая-то неведомая, ошибочная, алогичная логика. Я пол часа уже сижу и думаю исходя из какой логики гцц выпиливает именно этот код.

Почитай уже стандарт языка Си. У тебя о нём какие-то странные фантазии.

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

если заменить на void* my_realloc(void *p) { return p; }, то напечатает 2 и 2, так как эти 2 разные переменные указывают на одно значение. А для realloc именно UB, поэтому компилятор постулирует, что p и q ссылаются на разные значения. Вот и получается, что p == q, но *p != *q.

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

http://pastebin.com/ZvF79fid - вот. комментарии твоих комментариев. С тем с чем я согласен, я просто закоментил целиком.

В си ничего не пишут с абстракцией? т.е си по настоящему опревдывает тип «переносимый ассемблер»? и к нему и нужно так относиться?

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

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53265

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

Если UB, то можно делать что угодно. В частности, можно считать, что в этом случае происходит переход на начало цикла без проверки.

Опять балаболишь. Меня не интересуют твои убогие выводы, на которых ты уже обосрался.

Всё в этом мире работает исходя из реальной логики, а не из убого высера некомпетентных нулей. И никакой внятной логикой это поведение не описывается.

В этом случае никакого перехода на начало цикла не происходит.

Поэтому статически анализ показывает, что либо i < N, либо есть доступ к a, а значит можно делать что угодно. Значит всегда (по результату статического анализа) i<N.

Нет, в этом мире «всё что угодно» - есть только в твоих нулёвый представлениях.

Если «статически анализ показывает» выход за границы, то исходя из логики «можно делать всё, что угодно» - всегда будет делаться то, что логично - т.е. игнорироваться этот выход.

С чего ты, балаболка, приравняла «всё что угодно» == «удаление итерацией» мне не ведомо.

struct timeval tv;
unsigned long junk;
 	
gettimeofday(&tv, NULL);
srand((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);

И зачем ты это высрал? Ты настолько нулёвый, что не может привести пример безо всякого мусора?

unsigned long junk;
                  ^
                   = 0

Это абсолютно логичное поведение - считать неинициализированные переменные за ноль. Что меня должно здесь удивить?

Я уже писал про неопределённые значения.

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

Почитай уже стандарт языка Си. У тебя о нём какие-то странные фантазии.

Уважаемая балаболка, причём тут стандарт?

Ты мне кукарекаешь, что уб нарушает какое-то там поведение и делает его рандомным - тебе же говорят, что его поведение не «рандомно», а логично.

При это ты, балаболка, почему решил подменить понятие «неопределённое поведение» == «рандомное поведение» == «не работает». С чего? Какой жопой она стало рандомным, а потом какой жопой трансформировалось в «не работает»?

если заменить на void* my_realloc(void *p) { return p; }, то напечатает 2 и 2, так как эти 2 разные переменные указывают на одно значение.

Я же сказал вне видимости конпелятора. Не по этому. Запендюрь туда рестрикт - будет то же самое.

А для realloc именно UB, поэтому компилятор постулирует, что p и q ссылаются на разные значения.

Постулирует он это и для случая, который описал я.

В обоих случаях:

	movl	$1, (%rbx)
	movl	$2, (%rax)

Это пруфец.

К самим p и q это не имеет никакого отношения.

Я разобрался в чем проблема: «declare noalias i8* @malloc(i64) #1».

Все функции подписаны как noalias. http://clang.llvm.org/docs/AttributeReference.html#noalias - вперёд.

Они понапиханы там везде, причём форфан:

The realloc function returns a pointer to the new object (which may have the same

value as a pointer to the old object)

If memory for the new object cannot be

allocated, the old object is not deallocated and its value is unchanged.

И уб не имеют никакого отношения. Это оптимизация, которая не соответствует стандарту и никакого отношения к УБ не имеет.

noalias для realloc - это блаж, которая к стандарту не имеет никакого отношения, а вернее даже его нарушает.

Вот и получается, что p == q, но *p != *q.

Я знаю что получается. Молодец, что осилил перпастить мне объяснение из статейке.

Мне не надо описывать эти днищепримеры - мне надо отвечать на те вопросы, которые задаю я.

Мне не интересны твои рассуждения о том, что есть уб - зачем ты пытаешься сливаться на то, что типа я говорю «уб типа нет, либо можно юзать». Тебе конкретно говорят, что твоё объяснение поведения конпелятора - дерьмо. Всё.

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

Это абсолютно логичное поведение - считать неинициализированные переменные за ноль.

Перестань тупить. За ноль считается на значение junk, а (getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk.

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

Это оптимизация, которая не соответствует стандарту и никакого отношения к УБ не имеет.

раздел L.3 Стандарта ISO/IEC 9899:201x

All undefined behavior shall be limited to bounded undefined behavior, except for the following which are permitted to result in critical undefined behavior:

...

The value of a pointer that refers to space deallocated by a call to the free or realloc function is used (7.22.3).

...

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

http://pastebin.com/ZvF79fid - вот. комментарии твоих комментариев. С тем с чем я согласен, я просто закоментил целиком.

http://pastebin.com/V66EBH0Z

В си ничего не пишут с абстракцией?

Пишут, но абстракции не такого плана. Абстракции такого плана пишут только больные.

Зачем это писать на си, если если кресты?

Си для того и нужен, что ты жанглируешь сам как иллита. Интерфейсы и сокрытия - это совершенно другие подходы и языки.

т.е си по настоящему опревдывает тип «переносимый ассемблер»? и к нему и нужно так относиться?

Если ты не отбитый фанатик, то да.

Зачем страдать и ваять дырявое дерьмо, если можно проще и ровнее написать это на крестах?

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

комментарии твоих комментариев.

Кое на что отвечу:

вчем разниза если написать data[0]

Если data сделать неинициализированным (data[0] или ещё лучше data[]) и вставить в конец, то можно будет делать malloc один раз, а не два. С другой стороны, тогда при изменении длины строки может менять адрес этой самой строки, что не очень хорошо. Но у тебя dstr_insert и подобные возвращает «новую» строку. В общем, если указатель может меняться, то лучше объединить

= (dstring_t *)dstr_malloc

(void *) можно не кастовать к указателю

return DSTRING_SUCC_RESIZE

Традиционно в Си «успех» == 0. У тебя он 1 и в именованной константе.

dstr_fprint

Перепутаны местами аргументы (по сравнению с fprintf). И для широко используемого строкового типа лучше расширить *printf

dstr_insert

чем отличаются dstr_prepend(str, val) и dst_insert(str, val, 0)?

typedef struct dstring dstring_t;

Почему не «typedef struct dstring dstring;» ? А ещё лучше сразу «typedef struct { ... } dstring».

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

За ноль считается на значение junk, а (getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk.

А, да я посмотрел - ты мне вообще сбрехал.

1789771520

Где там ноль? Там нет никакого нуля - это он писал, что «пожалуйста инициализируйте переменную».

Где там за ноль считается знчение (getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk - у меня не считается.

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

Интерфейсы и сокрытия - это совершенно другие подходы и языки.

Что же ты скажешь про glib и gobject? Это ведь всё тоже Си.

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

раздел L.3 Стандарта ISO/IEC 9899:201x

Ответить по теме у балабола как всегда нечего.

Тебе дали конкретные цитатки из стандарта, которым noalias противоречит.

Твоя проблема в том, что ты нулёвая и некомпетентная балаболка. Тебе уже объяснили причину такого поведения на реаллоке - ты продолжаешь нести какую-то херню.

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

А потому, что там захотели пилители рантайма. При этом это поведение не соответствует стандарту и тебе это написали.

The value of a pointer that refers to space deallocated by a call to the free or realloc function is used (7.22.3).

Уважаемый ламерок, тебе кидали ссылки не когда оно особождается, а когда оно не освобождается. Зачем ты включаешь дурачка?

Когда реаллок зафейлился - указатель остаётся валидным и его значение так же. Это проверки в noalias не происходит.

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

Где там за ноль считается знчение (getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk - у меня не считается.

%%%. Из-за тебя пришлось clang ставить.

$ cat test.c 
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

unsigned long test()
{
  struct timeval tv;
  unsigned long junk;
 	
  gettimeofday(&tv, NULL);
  return (getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk;
}

int main() {

  printf("%lu %lu\n", test(), test());

}

$ clang-3.7 -O3 test.c
$ ./a.out 
0 0
monk ★★★★★
()
Ответ на: комментарий от PotentialCppTsar

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

Верно, но в этом случае realloc вернёт NULL и алиаса всё равно не появится. Или я «noalias» не так понимаю?

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

но в этом случае realloc вернёт NULL и алиаса всё равно не появится

Так как q потом разыменовывается, компилятор вправе считать, что realloc вернёт не NULL.

i-rinat ★★★★★
()
Ответ на: комментарий от monk

И ещё одно - стандарт не описывает реализацию - стандарт описывает поведение и то обсирается в 95% случаев.

С чего убогие решили, что если в стандарте написано, что это уб - в реальной реализации это уб? Абстрактный мусор интересует лиспанонейм балаболов. Поведение реализации имеет больший приоритет, чем описание, по которому эта реализация делалась, особенно если это описание состоит на 95% из дыр.

Зная поведение реализации я знаю поведение и описание, которому она соответствует. Ты же не зная поведение реализации - кукарекаешь и несёшь херню.

При это меня нули всегда удивляют своими куллстори. Ты типа мне пытаешься открыть глаза или что? Или ты думаешь, что ты мне показал что-то новое. Я не понимаю мотивации нулей.

Это я ещё не начал множить тебя банальным доводом «твой код не имеет смысла», а раз твой код не имеет смысла, то без разницы как работает то, что итак не имеет смысла.

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

и алиаса всё равно не появится. Или я «noalias» не так понимаю?

Ты прав. тут я «серанул». Только там ещё есть:

The realloc function returns a pointer to the new object (which may have the same

value as a pointer to the old object), or a null pointer if the new object could not be allocated.

Стандарт допускает эквивалентность входящего и исходящего значения указателя. Поэтому тут noalias обделался и не соответствует стандарту.

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

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

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