LINUX.ORG.RU

В Си предложили добавить switch-case для строк

 , ,


0

3

Привет, чат!

Спустя много лет, в язык Си наконец предложено добавить возможность использовать выражение switch-case для строк. Например, можно будет писать вот такое:

const char *s = get_some_string();

switch(s) {
case "this":
  handle_this();
  break;
case "that":
  handle_that();
  break;
default:
  handle_other();
  break;
}

Таким образом, в Си будет чуть меньше способов отстрелить себе ноги.

Ссылка на предложение: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3895.pdf



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

Я вот, например, не очень жалую некоторые решения моего начальника. Что мне теперь, саботировать деятельность компании? Есть собственное мнение, и это хорошо, а ещё есть общество и здравый смысл. Вы можете сколько угодно не уважать ISO стандарты, но суть от этого не изменится: по ISO стандарту printf всё равно является частью языка. Поэтому разумнее так и говорить, «Я, фирках, не считаю решение ISO правильным и не включаю в своё определение языка Си библиотечные функции» вместо упёртого и дебильного «В Си printf не входит и неибхх.”

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

Ну понятно, это был ноябрь 2023. Теперь понятно, почему я ничего не знаю про его желание учиться и отношение к Си стандартам. В те времена я на ЛОР ходил не часто, было чем заняться.

Спасибо!!! А то я тут в стенку бьюсь.

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

сколько угодно не уважать ISO стандарты

Уточню - речь не про ISO-стандарты вообще, а конкретно про Cxx.

но суть от этого не изменится: по ISO стандарту printf всё равно является частью языка

Да это то я в курсе, но реальность от этих надписей отличается. Хотя в компиляторы в последнее время и встроили варнинги про printf-форматы и типы аргументов, printf это всё же внешняя по отношению к языку функция.

Поэтому разумнее так и говорить, «Я, фирках ... считаю

Всё, что я пишу - это то, что я считаю. И у большинства людей так же (хотя бывают и такие, кто регулярно озвучивает не своё а чужое мнение, но не будем о печальном). Каждый раз делать это уточнение - флуд. Даже по твоей предлагемой надписи видно: вместо строки их примерно 20-25 символов строка из примерно 80-100 символов, на 75% заполненная бесполезной информацией. В обогащении надписей флудом преуспели LLM, их я тоже осуждаю.

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

Вы случайно повышение по службе не получали за последние год-два?

VIT ★★
()

Эммм... А что, НЕ БЫЛО??

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

Скорее парашют, развивается за плечами, ноги путаются…

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

printf это всё же внешняя по отношению к языку функция.

Интереса ради, можно примеры внутренних по отношению к языку функций?

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

В общем случае их нет. А в частных бывают компилятороспецифичные builtin (у gcc в мануале имеются, что-то там для атомиков вроде было, не помню, и не только они). Хотя с другой стороны возможно не стоит их функциями называть если они всегда инлайн. Точнее в случае с gcc вроде даже не так - есть _builtin_xxx внутренние компилятора и есть макросы в каких-то хедерах которые мапят их на имена из мануалов - это чтобы они без нужного хедера не работали. Но по builtin имени их можно и без хедера вызывать.

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

ISO (вместе в DIN и ASTM) - примерно такая же хрень как и ГОСТы. Только ещё хуже, потому что у нас туда пихают чушь просто по недомыслию, а там из невменяемой корысти. У меня вон целая пачка стандартов этого ISO валяется которые были написаны исключительно с целью монополизации рынка и продажи измерительных приборов какой-нибудь фирмы, которая этот стандарт и продвинула. Тупо описания способа измерения из своего патента в стандарт копировали, да и всё. А то и вовсе Самое смешное, что половина этих хитрожопых фирм уже давно не существует, все эти приборы давно сдохли, а ссылки на эти стандарты до сих пор в куче других, активно используемых стандартов содержатся. :) Китайцы в последнее время, конечно, подсуетились, и некоторые приборы соответствующего принципа действия выпускают (правда всё-равно не рискуют например, свои измерялки белизны называть Leucometer’ом в официальной документации, ибо трейдмарк, но в рекламе продаванов - сплошь и рядом - Whiteness meter, Leucometer). Но, увы, китайцы выпускают далеко не все подобные приборы, которые гвоздями приколочены к ISO стандартам но фирмы их выпускавшие (и продвинувшие эти стандарты) давно ушли в небытие.

А ещё, эти говнюки в ISO, DIN и ASTM бабло за текст стандарта требуют. Хорошо нашлись разумные западные человеки которые слили большую часть стандартов ISO на торренты. Не все, к сожалению, но весьма значительную часть.

Так что крайне не рекомендую ко всем этим ГОСТам и ISO относится как к чему-то неимоверно авторитетному и обоснованному. В большинстве случаев стандарты, особенно западные, вовсе не про это.

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

Никто не утверждает, что стандарты ISO Cxx — это хорошие, годные стандарты. Просто современные компиляторы следуют тому, что там написано, включая эксплуатацию неопределённого, по стандарту, поведения (с небольшими оговорками, описанными в документации к компиляторам, и ключами типа -fwrapv — но нет, например, ключа, который бы отключал презумпцию обязательного выравнивания всех объектов типа type на _Alignof(type)).

shdown ★★
()
Последнее исправление: shdown (всего исправлений: 2)
Ответ на: комментарий от firkax

Интереса ради, можно примеры внутренних по отношению к языку функций?

В общем случае их нет.

Там выше @r--r--r-- писал, что тебе нужен LISP, но он ошибается. Тебе нужен Forth. Вот это реально тот язык, который ты тут хочешь описать, по незнанию наделяя его образом Си.

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

но нет, например, ключа, который бы отключал презумпцию обязательного выравнивания всех объектов типа type на _Alignof(type)).

#pragma pack(1)?

Stanson ★★★★★
()
Ответ на: комментарий от shdown
#pragma pack(1)
typedef int my_int;

my_int my_func(my_int *p, my_int *q)
{
    *p = 1;
    *q = 1;
    // assignment to *q might have altered *p if pointed-to objects partly overlap
    return *p;
}

Пажжи, я не очень понял. А причём тут выравнивание?

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

Ну смотри, компилятор на -O3 это преобразует в

  *p = 1;
  *q = 1;
  return 1;
Это потому, что он подразумевает, что либо p и q равны, либо они указывают на *непересекающиеся* объекты.

O3: https://godbolt.org/z/ebbdWEjvn

O0: https://godbolt.org/z/3axx4hscj

P.S.: launder() там просто для того, чтобы показать, что дело в самой функции, а не в том, как компилятор её вызывает. Можно сделать static void launder(void *p) { return p; }, на этой версии компилятора получается то же самое.

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

Это потому, что он подразумевает, что либо p и q равны, либо они указывают на непересекающиеся объекты.

Выравнивание тут не причём. Это алиасинг. Ключ -fno-strict-aliasing уже существует. Алсо, ты присваиваешь 1 в любом случае, поэтому компилятор даже с этим ключом заоптимизирует и вернёт 1.

Держи, я починил твой говнокод. Теперь он печатает говно, как ты и хотел.

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

Выравнивание тут не причём. Это алиасинг.

Ключ -fno-strict-aliasing уже существует.

Алсо, ты присваиваешь 1 в любом случае, поэтому компилятор даже с этим ключом заоптимизирует и вернёт 1.

Выравнивание тут ни при чём. Это алиасинг. Но код с -fno-strict-aliasing всё равно вернёт 1. (А ещё я поменял код my_func, и теперь оно печатает другое!)

Странно как-то, не находишь?

(Я знаю, как продемонстрировать, что это выравниваниие, но хочу немного потроллить Stanson’а перед этим.)

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

(А ещё я поменял код my_func, и теперь оно печатает другое!)

Странно как-то, не находишь?

Нет. Если ты добавишь volatile, всё будет ровно как ты хочешь.

my_int my_func(volatile my_int *p, my_int *q)
{
    *p = 1;
    *q = 1;
    // assignment to *q might have altered *p if pointed-to objects partly overlap
    return *p;
}

Всё ещё не вижу, как это связано с выравниванием.

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

Ещё раз:

1. Выравнивание тут ни при чём. Это алиасинг.

2. Но код с -fno-strict-aliasing всё равно вернёт 1.

Ты не видишь здесь противоречия? При чём тут, прости хоспади, volatile?

shdown ★★
()
Последнее исправление: shdown (всего исправлений: 1)
Ответ на: комментарий от shdown
  1. Выравнивание тут ни при чём. Это алиасинг.2. Но код с -fno-strict-aliasing всё равно вернёт 1.

Да, тут ты прав, это я нагнал. Алиасинг сработал бы, если бы параметры были разных типов.

При чём тут, прости хоспади, volatile?

Тебе нужно вынести модификацию одного из параметров в ранг наблюдаемых побочных эффектов. volatile именно это и делает. В противном случае, запись любой переменной с последующим возвратом её значения из функции можно вот так же оптимизировать. Если ты знаком с оптимизацией SSA, вот это вот ровно оно.

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

Тебе нужно вынести модификацию одного из параметров в ранг наблюдаемых побочных эффектов. volatile именно это и делает. В противном случае, запись любой переменной с последующим возвратом её значения из функции можно вот так же оптимизировать. Если ты знаком с оптимизацией SSA, вот это вот ровно оно.

Ага. А что ты хотел продемонстрировать этим кодом с volatile?

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

Ага. А что ты хотел продемонстрировать этим кодом с volatile?

Вот этот ассемблерный листинг:

"my_func":
        mov     DWORD PTR [rdi], 1
        mov     DWORD PTR [rsi], 1
        mov     eax, DWORD PTR [rdi]
        ret

Я так понимаю, твоя жалоба была в том, что компилятор не даёт тебе вот это? Теперь даёт.

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

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

Нет, мне нужен не Lisp и не Forth, а Си. И на данный момент gcc более-менее соответствует требованиям. Позже требованиям будет 100% соответствовать мой собственный компилятор Си.

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

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

Хорошо, давай попробуем сократовский диалог и наскальные рисунки.

char buf[128] = {0};
int *a = (int *) buf;
int *b = (int *) (buf + 1);

[ 0    0    0    0    0    0    ... ]
  ^^^^^^^^^^^^^^^^    ↑
  a    ↑              ↑
       ^^^^^^^^^^^^^^^^
       b

Мы присваиваем *a=1:

[ 1    0    0    0    0    0    ... ]
  ^^^^^^^^^^^^^^^^    ↑
  a    ↑              ↑
       ^^^^^^^^^^^^^^^^
       b

Мы присваиваем *b=1:

[ 1    1    0    0    0    0    ... ]
  ^^^^^^^^^^^^^^^^    ↑
  a    ↑              ↑
       ^^^^^^^^^^^^^^^^
       b

Мы читаем *a:

[ 1    1    0    0    0    0    ... ]
  ^^^^^^^^^^^^^^^^     
  a
*a должно быть 1 * 256 + 1 = 257. Но оно 1. Почему так?

Какую именно оптимизацию, по-твоему, убирает твой volatile?

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

Думаю, дело в том, что два выровненных int-а пересекаются либо полностью, либо никак, и поэтому единица там не может измениться на что-то другое, а вот два невыровненных могут пересекаться частично и дать 0x010001 например. Но вообще pragma pack() насколько я знаю влияет на упаковку структур, а не на подразумеваемое выравнивание произвольных указателей, так что мне тоже непонятно при чём тут оно.

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

Но вообще pragma pack() насколько я знаю влияет на упаковку структур, а не на подразумеваемое выравнивание произвольных указателей, так что мне тоже непонятно при чём тут оно.

Ну так Stanson предложил вместо флага компилятора просто на нужные типы навешивать #pragma pack(1). Помогло это? Нет, не помогло.

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

Тебе никто не запрещает в твою функцию передавать совершенно произвольные указатели, хоть выровненные, хоть нет. Наличие ошибок и варнингов определяется железом. Есть архитектуры которые физически не могут, например, загрузить в 32хразрядный регистр содержимое 4 последовательных байт памяти, в начальном адресе которых последние два бита не равны 00. Почти все компиляторы, которые не считают это фатальной ошибкой могут наваливают проверку на выравнивание и собирание 32хразрядного числа побайтово, или посредством всяких and + shift. Это занимает время, и вполне логично, что об этом стоит предупреждать.

‘#pragma pack()’ позволяет упаковывать структуры с произвольным (обычно кратным степени двойки) выравниванием элементов, и, во-первых, позволяет без пердолинга читать/писать упакованные структуры из/в внешний мир (который, сцуко, совершенно не обязан быть x86_64, которые, внезапно, занимают ничтожную долю от используемых процессорных архитектур), а во-вторых позволяет экономить память жертвуя временем доступа.

Собственно, в основном именно в структурах можно столкнуться с необходимостью отключить выравнивание, поэтому я и написал про #pragama pack().

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

У тебя не получится меня потроллить, просто потому что ты про каких-то сферических коней в вакууме рассуждаешь. Тебе my_func вообще для чего нужна? Какая задача в общем, не в частности.

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

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

А твоя непонятка решается вообще без проблем, всего лишь перемещением одной звёздочки в нужное место и добавлением другой. :) :

#include <stdio.h>

int * my_func( int* p1, int* p2 )
{
    *p1 = 1;
    *p2 = 1;
    return p1;
}

int main()
{
    char buf[sizeof(int)+1];
    printf( "%d\n", *my_func( (int*)buf, (int*)(buf+1) ) );
}

Правильный ответ при любых оптимизациях. Только нахера тут вообще my_func и нахера int я всё равно не понимаю. На всякий случай принёс тебе звёздочек - ******************************. Мне не жалко, пользуйся.

Stanson ★★★★★
()
Последнее исправление: Stanson (всего исправлений: 2)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.