C++11 countof

Наверняка многие используют макрос, подобный нижеприведенному:

#define countof(array) (sizeof(array)/sizeof(array[0]))

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

Благодаря constexpr появившемуся в C++11 есть возможность сделать безопасный countof.

template <class T, size_t N>
constexpr size_t countof(const T (&)[N]) noexcept
{
    return N;
}

Теперь на этапе компиляции произойдет ошибка:

const int values[] = { 42, 76, 16, 11, 31 };

void foo(const int v[])
{
   for (size_t i = 0; i < countof(v); ++i) // <-- compilation error!
   {
      bar(v[i]);
   }
}

Версия для C++98 может быть такой:

template <typename T, size_t N>
char (&CountOfHelper(T(&)[N]))[N];
#define countof(x) sizeof(CountOfHelper(x))

Emscripten + OS X El Capitan

Emscripten Emscripten is an LLVM-based project that compiles C and C++ into highly-optimizable JavaScript in asm.js format. This lets you run C and C++ on the web at near-native speed, without plugins.

Решил еще раз установить Emscripten с помощью brew, на сей раз все оказалось гораздо проще. Возможно это работало и раньше, но я только сегодня обратил на это внимание.

Правильный способ установки Emscripten с помощью brew:

# устанавливаем emscripten как обычно:
$ brew install emscripten

# запускаем emcc, что бы он создал файл ~/.emscripten
$ emcc

# исправляем LLVM_ROOT:
$ vim ~/.emscripten

Должно получиться как-то так:

LLVM_ROOT = '/usr/local/opt/emscripten/libexec/llvm/bin'

К сожалению с помощью brew правильно установить emscripten под OS X El Capitan мне не удалось.
Я не смог найти какую-либо информацию по правильной установке emscripten с помощью brew, поэтому получилась вот такая магическая инструкция.

Список шагов для установки emscripten из-под OS X:

  • С официального сайта качаем портабельную версию emscripten – http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html#sdk-download-and-install
  • Распаковываем и запускаем ./emsdk update.
  • С помощью команды ./emsdk list можно посмотреть список доступных пакетов, утилит и sdk.
  • С помощью комады ./emsdk install latest устанавливаем самые последние версии.
  • Командой ./emsdk activate активируем переменные окружения emscripten.
  • Теперь при необходимости сборки проекта инициализируем переменные окружения с помощью команды source ./emsdk_env.sh.
  • По желанию можно прописать путь к директории с emsdk.

Gradle, Lint: [MissingTranslation]

Иногда не нужно делать локализацию всех строк. К примеру, зачем переводить идентификаторы сетей или прочие технические данные.

Если нужно полностью подавить сообщение об ошибке, то в build.gradle достаточно добавить такие параметры:

lintOptions
{
   disable 'MissingTranslation'
}

Если нужно подавить сообщение об ошибке только для определенных файлов, то добавляются такие атрибуты в каждый файл:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">

CPU time

#include <sys/resource.h>
#include <sys/time.h>

unsigned GetSystemTime()
{
    rusage ru;
    if(::getrusage(RUSAGE_SELF, &ru) != -1)
    {
        return (unsigned)(ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec);
    }

    // fallback
    timeval time;
    ::gettimeofday(&time, 0);

    return (unsigned)(time.tv_sec * 1000000 + time.tv_usec);
}

GLSL: Clock style bar

Clock (GLSL) Написал GLES шейдер, который имитирует круговое заполнение энергии (прогресса, маны, etc.). Код шейдера и демонстрация работы доступна на сайте ShaderToy.

#define M_PI 3.1415926535897932384626433832795

vec4 col = vec4(0.0, 0.0, 0.0, 0.0);

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float angle = mod(iGlobalTime, M_PI * 2.0);

    vec2 p = (iResolution.xy - 2.0 * fragCoord.xy) / iResolution.y;

    float q = atan(-p.x, p.y);
    float f = step(0.0, cos((q + angle) * 0.5));

    // mix with texture
    vec2 uv = fragCoord.xy / iResolution.xy;
    vec4 tc = texture2D(iChannel0, uv);
    fragColor = mix(tc, col, f);
}

Время в миллисекундах

Возвращает использование времени в миллисекундах для вызвавшего процесса и всех его нитей:

#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>

int getCpuTime()
{
  struct rusage rus;
  getrusage(0, &rus);
  return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
}

Подробности в man getrusage.

Boot Demo

Boot Demo Нашел у себя в файлопомойке свою первую демку для x86 от 1997 года. Помню, что эта демка была написана вначале на Си и на i386 SX она жестоко тормозила. Тогда я переписал ее на ассемблере (это был мой первый опыт программирования на ассемблере для x86). И она шустро работала на всем том говне, которое можно было найти в то время.

С помощью утилиты Demoinst (автор Алексей Шаблюк) демка записывалась в свободные сектора на HDD и устанавливался бут, который ее запускал. После включения и инициализации компьютера запускалась эта демка, а по нажатию на любой клавиши запускался оригинальный загрузчик. Тогда это казалось прикольно :)

Запустить демку удалось только под DosBox. При запуске в DosEmu эмулятор крешится (Fault out of DOSEMU code, cs:eip=33:4a5563, cr2=11cf, fault_cnt=1). В демке нет поддержки v-sync, поэтому она в эмуляторе мерцает.

p.s. Сейчас для меня кажется странным, что такое простое приложение на Си могло быть таким тормозным. Вероятно мой Си-кунг-фу был низкого уровня.

1 2 3 69