Ответы пользователя по тегу C
  • Можно ли удалить пробелы в начале и в конце строки без создания нового массива?

    @Mercury13
    Программист на «си с крестами» и не только
    Строковый литерал " ab " находится в особом сегменте данных, который (если процессор и ОС позволяют) только для чтения. А память сегмента данных освободить и сделать «кучей» нельзя.

    Если предположить, что текст " ab " находится в «куче» — эта самая куча является сложной структурой данных и память выделяется с выравниванием. Потому функция realloc может (но не обязана) отдать конец или приделать память к концу. Отдать начало будет сложнее, и ни одна известная мне библиотека функций на это не способна.

    Кроме того, Си++ придумал объект string_view именно для этого — чтобы передавать строки в функцию, абстрагируясь от выделения памяти и даже от оконечного нуля. Потому у string_view нет функции c_str().

    Разумеется, вы можете сделать что-то вроде
    char* str2 = str + 2;
    str2[2] = '\0';
    // А str оставь, уничтожать как-то придётся

    Разумеется, если str находится в куче. Сегмент с литералами, напоминаю, только для чтения, и в ОС вроде DOS, где менять можно, такая замена может вызвать нехорошие побочки.
    Ответ написан
    3 комментария
  • Не могу понять почему пишет функция перегружаная 1 ошибка?

    @Mercury13
    Программист на «си с крестами» и не только
    Тут причины не видно, она за правой границей экрана. Вероятнее всего, вы открыли или закрыли лишнюю скобку, из-за чего sqrt стала с двумя аргументами.
    Ответ написан
  • Возможно ли в процедурном программирование, имитировать ООП?

    @Mercury13
    Программист на «си с крестами» и не только
    Можно, и я бы посоветовал посмотреть на две вещи.
    1. MiniZip. Настоящие виртуальные потоки, написанные на чистом Си!
    Кстати, у нас на работе есть библиотека MiniZipPort, представляющая собой тупой перевод MiniZip на виртуальные потоки и шаблонные контейнеры — две строчки Си превращались в одну строчку на «крестах». К тому же для хранения каталога я использовал уже имевшийся самописный AccuStream (что-то вроде std::deque, только в виде потока).
    2. Doom. Самый первый, 1993–94 года. Там тоже ухитрились делать объектно — правда, другими методами.
    Ответ написан
    3 комментария
  • Как прочесть аргументы функции на стеке / заставить gcc хранить аргументы функции на стеке?

    @Mercury13
    Программист на «си с крестами» и не только
    https://godbolt.org/z/ARYhis
    Если посмотреть в пролог функции, она делает локальную копию нашей a. А желаемое место в стеке на 36 байтов выше, чем вы ищете.
    Разумеется, всё под x86. Вызов под x64 подразумевает регистры.

    UPD. А вот Интел не делает локальных копий и всё на месте.
    Ответ написан
    Комментировать
  • Ошибка при чтении из файла в си.Что делать?

    @Mercury13
    Программист на «си с крестами» и не только
    feof возвращает true, когда мы попытались прочитать и не смогли, потому что каретка ударилась в конец файла. А не когда каретка аккуратно припарковалась в конце файла — и уж тем более не когда она отделена от конца пробелами.

    Лучше прочитайте про scanf…
    On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.

    …и посмотрите, как можно переделать условие цикла.
    Ответ написан
    Комментировать
  • Не работает функция. Что сделать?

    @Mercury13
    Программист на «си с крестами» и не только
    Я пока вижу…
    shitf_up(s,Parent);

    Может, ещё вы напутали с порядком кучи, но на таком кусочке кода этого не видно.
    Ответ написан
  • В чем ошибка?Обьясните в чем ошибка?

    @Mercury13
    Программист на «си с крестами» и не только
    Вместо знака умножения плюс стоит.
    beforeTax = tirePrice + numTires;

    .07 — это очень некузявая запись для 0.07, ставки налога. Знаете же, что в США налоги зависят от кучи параметров, и их надо прибавлять вручную.
    Ответ написан
    Комментировать
  • Почему pow возвращает разные значения от одинаковых float значений?

    @Mercury13
    Программист на «си с крестами» и не только
    У меня на свежайшем MinGW (Си, режим C99) не получилось повторить, а погрешность на пределе double — так что подозрение на runtime-библиотеку и управляющее слово сопроцессора (x87 control word).
    Ответ написан
    Комментировать
  • Почему void ** можно инициализировать только void *?

    @Mercury13
    Программист на «си с крестами» и не только
    К.О.: Потому что void* — это не void. Первый — это вполне конкретный тип, второй — «псевдотип», используемый в двух контекстах.
    Ответ написан
    Комментировать
  • Как вывести массив строк в Си?

    @Mercury13
    Программист на «си с крестами» и не только
    Ваши ошибки.
    1. Вы считываете строку куда попало. Надо выделить память, или сделать статический массив char s[3][40];
    2. Обозначение для символа перевода строки — \n, с обратным слэшом.
    3. *a = a[0].
    Ответ написан
    2 комментария
  • На каких правилах основана шестнадцатеричная нотация в printf для вещественных чисел?

    @Mercury13
    Программист на «си с крестами» и не только
    Что собой представляет 17? Это 100012, или 1,00012·24, или 1000,10002·21. Теперь видите, откуда две восьмёрки и порядок 1? Правильно не 0x1.1p+1, а 0x1.1p+4.

    На основании каких правил — не могу сказать, думаю, какая-то оптимизация. Подождите, скачаю Qt, выяснилось, что на домашнем компе не осталось ничего прогерского.

    Моя первая догадка. Если исходное число было float, то первая цифра 8…F тупо проще: отрезаешь порядок и знак, добавляешь неявную единицу, и получаем 24 бита, шесть шестнадцатеричных цифр.

    Действительно библиотека MinGW выводит первую цифру 8…F, что для float, что для double. Зачем, не знаю.
    Ответ написан
    Комментировать
  • Посимвольный i/o vs i/o в строку (буфер)?

    @Mercury13
    Программист на «си с крестами» и не только
    Очень-очень верно! Даже на чём-то типа istringstream виртуальный вызов занимает довольно много времени, и ОЧЕНЬ желательна буферизация своими силами.
    Подтверждаю, приходилось писать код скоростного разбора XML.
    Ответ написан
    Комментировать
  • Правилен ли такой подход к разбиению C приложения на модули?

    @Mercury13
    Программист на «си с крестами» и не только
    Смотря в чём задача.
    Возможно, нет никаких проблем.
    Возможно, удастся вытащить общую функциональность в defines.h.
    Возможно, удастся каким-то образом разорвать порочный круг. Например, в ООП это можно делать через интерфейс.
    Ответ написан
    Комментировать
  • Как организовать указатели в си?

    @Mercury13
    Программист на «си с крестами» и не только
    Дело тут в очерёдности операций.
    Сначала вычисляются правые одноместные, потом левые.

    Надо (**h)[1] = 0;.
    Ответ написан
    Комментировать
  • И снова clang: Почему (при оптимизации) реализация на указателях получилась хуже чем с использованием оператора [ ]?

    @Mercury13
    Программист на «си с крестами» и не только
    Интересно тут другое. Компилятор первую версию превращает во вторую — базово-индексная адресация очень быстра, а дважды прибавлять единицу — не лучший вариант. К тому же он обнаруживает параллельные циклы и устраивает им одинаковый индекс.

    Кстати, посмотри интереса ради gcc -Os.
    Ответ написан
    6 комментариев
  • Почему не работает код на Си?

    @Mercury13
    Программист на «си с крестами» и не только
    Я пока вижу
    printf("%f", a);
    Не нужно брать адрес у a.

    while(s>=0.0001)
    1) Дробные числа во всех ЯП записываются через точку. Кое ради какой вещи (параллельные циклы) в Си есть операция «запятая», так что код может даже компилироваться.
    2) Цикл не выполнится ни разу, т.к. 0 < 0,0001.
    Ответ написан
    Комментировать
  • Как не переноситься на следующую строку после scanf?

    @Mercury13
    Программист на «си с крестами» и не только
    Без особого консольного API той или иной ОС — никак. Потому что строка передаётся в консоль, когда пользователь нажимает на ввод.
    Ответ написан
    Комментировать
  • Почему неправильный вывод значений в printf?

    @Mercury13
    Программист на «си с крестами» и не только
    У меня вышло: 0 1074266112 0 1074266112
    Или, в 16-й системе, 0 40080000 0 40080000

    Связано это с такими вещами.
    1. Аргументы типа float записываются в стеке как double.
    2. На x86 порядок байтов Intel (обратный).
    3. Дробные числа хранятся без ведущего разряда (который всегда 1), в формате мантисса-порядок-знак (на порядке байтов Intel).
    4. Для единицы (xxx·20) порядок будет 011…11.

    3 = 1,10…02·2¹, и с учётом отброшенного ведущего разряда мантисса будет 10…0.
    Порядок 011…11 + 1 = 10…0.

    С учётом обратного порядка байтов double 3,0 будет выглядеть так
    • 6 нулевых байтов — мантисса
    • 0000.1000: нижние полбайта — это мантисса, верхние — уже порядок
    • 0100.0000: бит знака и ещё семь битов порядка

    Получается 00.00.00.00.00.00.08.40.
    Разбиваем на два куска памяти по 4 байта.
    [00.00.00.00] [00.00.08.40]
    Опять-таки не забудем, что у целых тоже обратный порядок байтов — и получается 0 и 40080000.
    Ответ написан
    Комментировать
  • Почему не переполняется float?

    @Mercury13
    Программист на «си с крестами» и не только
    Представьте, у нас десятичная арифметика с тремя значащими цифрами. Соответственно, сложение работает не более чем с пятью цифрами: три собственно значащих, слева на перенос и справа на округление. То, что получилось, в любом случае будет округлено до трёх.
     99900000000000
    +             1,00
     -----------------
     9990   →   9,99e13

    Если сделать второе слагаемое покрупнее, то будет
     99900000000000
    +   50000000000
     -----------------
     9995   →   1,00e14 → переполнение


    То есть вот что надо добавить, чтобы случилось переполнение: в зависимости от настроек сопроцессора или ulp(FLT_MAX) (ULP = Unit of Last Place — цена младшего разряда на данном порядке), или ulp(FLT_MAX)/2.
    Ответ написан
    Комментировать
  • Как исправить ошибку при компиляции файла.c в MinGW?

    @Mercury13
    Программист на «си с крестами» и не только
    Вот и положите этот libmingwex-0.dll в каталог с программой. Всё в порядке, программа скомпилировалась, остаётся пустить.
    Если такое случается при запуске компилятора — что-то с компилятором, и переустановить надо ЕГО.
    (Покопался по интернету, завтра проверю на работе свежие версии MinGW)
    Ответ написан
    Комментировать