Задать вопрос
Ответы пользователя по тегу C
  • Почему при выводе элемента из перечисления выводит не нужное мне значение?

    @Mercury13
    Программист на «си с крестами» и не только
    Полагаю, дело в системе сборки — нечто подобное я испытывал и в Doom (старом, 1994 года), где makefile редактировался руками.

    Например, у вас было
    typedef enum Buttons{
        SAVE,
        OPEN,
        SORT,
        EXIT
    }Buttons;

    После того, как вы откорректировали enum, один файл перекомпилировался, другой нет — отсюда такой артефакт.
    Ответ написан
  • Почему при вводе текста добавляются лишние символы?

    @Mercury13
    Программист на «си с крестами» и не только
    Я сделал вот такой код (простите, для простоты «с крестами»).
    #include <stdio.h>
    #include <iostream>
    
    int main() {
        int a = getchar();
    
        while (a != '\n') {
            std::cout << a << "-" << static_cast<char>(a) << std::endl;
            a = getchar();
        }
    }
    
    143-П
    224-р
    168-и
    162-в
    165-е
    226-т

    Так что не здесь полом. Но учтите, что работа была под виндой, а значит, в кодовой странице DOS-866. Подкиньте ОС, рабочую кодировку и чуть больше кода обвязки.

    UPD1. Если символов 12 вместо 6 и ОС Android — перед нами кодировка UTF-8. И выводить в консоль по одному символу не очень кузяво, поскольку для русского текста получаются неполные кодовые позиции. Закройте буфер нулём и выведите целиком.
    Ответ написан
  • Почему прошивки пишут на С?

    @Mercury13
    Программист на «си с крестами» и не только
    Потому что низкоуровневый софт должен…
    • Быстро выполняться. Потому что его выполняют или в глубоких циклах (например, ОС), или на слабом железе.
    • Расходовать мало памяти и не «течь». Потому что его часто выполняют на слабом железе. Или в чужих стеках, как драйвер.
    • Содержать мало зависимостей. Если мы зависим от большой библиотеки вроде Qt, а её реализации на данной машине нет — выкуси. Точно так же интерпретатор Питона может оказаться лишней зависимостью. И многопоточка, которая часто требуется для «мусорщика».
    • Быть совместимым с кодом на других языках. Это касается системного и драйверного кода, который вызывают из прикладного ПО (или, наоборот, прикладной кода из системной проги) — и даже с кодом на разных версиях .NET в расширениях оболочки Windows есть вопрос.
    • И в то же время требуется некая доля переносимости и абстракции. Например, мы пишем джойстик на AtMega и не хотим мучиться с длинными числами — ЯВУ лучше будет, чем ассемблер. 10 бит АЦП на 8-битном процессоре уже длинное число!!

    Почему Си? У него есть две фишки: большое поле для ручной оптимизации (ключевое слово register, op++), и он полагается на две ассемблерных утилиты — линкер и библиотекарь (tlink и tlib, например). Из-за этого компилятор Си довольно просто написать под новую машину, и на НЕоптимизирующем компиляторе можно писать довольно быстрый код.
    Ответ написан
    Комментировать
  • Что не так в Eclipse IDE?

    @Mercury13
    Программист на «си с крестами» и не только
    printf("%c", x);
    Форматную строку упустил.
    Ответ написан
    1 комментарий
  • Можно ли удалить пробелы в начале и в конце строки без создания нового массива?

    @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 комментариев
  • Как не переноситься на следующую строку после scanf?

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