LINUX.ORG.RU

Валидное ли это c-выражение?

 ,


0

4

subj:

void foo(char *a, char b, char c) {
	(a ? *a : b) = c;
}

GCC съедает без проблем, SDCC ругается что слева не lvalue.

upd. Под плюсами корректное, под си нет.

upd#2, solution.

★★★★★

Последнее исправление: thunar (всего исправлений: 5)
Ответ на: комментарий от MKuznetsov

Косвенно оно возвращает c в *a если там не нулевой указатель.
Сделано это чтобы можно было инициализировать

int &r = cond ? a : b;
в c++, в c соответсвенно такой необходимости нет и выражение невалидно

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

Этот фокус нужно делать так:

#include <iostream>

int main()
{
    int* a = new int;
    *a = 4;
    
    // int* a = nullptr;

    int b = 5;

    *(a ? a : &b) = 10;

    if (a)
        std::cout << "a=" << *a << std::endl; 
        
    std::cout << "b=" << b << std::endl;
}
rumgot ★★★★★
()

(a ? *a : b) = c;

А в чем смысл этого выражения? Ну то есть если a=NULL, то измениться должна локальная копия b?

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

Тут важен сам механизм присваиваивания. Для C оно будет выглядеть так же. И для char тоже. Ты по сути скажи что-то лучше. А то нашёл тоже, к чему докопаться, смехота.

rumgot ★★★★★
()

не надо так писать, даже если это валидное выражение.

#define SET_A(a, b, c) ((__builtin_types_compatible_p(typeof(a), char*) && (a)) ? (*(char*)(a) = c) : (b = c))

не претендую ни на что, но все-таки понятнее вашего и ф-цию не надо новую писать, и b все-таки не в пустую присваивается значение, но это gnu99, не C99.

А в C11 уже добавили полноценную стандартную проверку типов.

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

но вообще, такую вещь удобнее и логичнее оформить как ф-цию, тогда проверки пройдут автоматически, но тогда мы вернемся к первому моему утверждению - «не стоит так писать»

IvanRia
()

на мой взгляд для C++ действует это правило:
https://eel.is/c draft/expr.cond#5

для C насколько я могу судить должно быть тоже самое (очень невнятно там это изложено, как думается):
https://cstd.eisie.net/c23.html#6.5.16

хотя нет — поулчается всё так и есть — оно rvalue там:
«the result is the value of the second or third operand (whichever is evaluated), converted to the type described subsequently in this subclause.110)
110)A conditional expression does not yield an lvalue.»

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

Зато локалевые костыли в printf всё равно жрут боольшую часть производительности.
Но локали в форматере не нужны, ими всё же должны заниматься специализированные библиотеки

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

Но локали в форматере не нужны, ими всё же должны заниматься специализированные библиотеки

что тут подразумевается под «форматером»? можно ли тут формализовать «нужновость» локали, а так же определить критериальностности отнесения к таковому? что значит «специализированные библиотеки», можно ли это формализовать, а так же определить критериальностности отнесения к таковому? чем std::locale не является достаточно специализированной?

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

что тут подразумевается под «форматером»?

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

можно ли тут формализовать «нужновость» локали, а так же определить критериальностности отнесения к таковому

Довольно сложный вопрос. Я, например, не вижу смысла в существовании codepage-локалей в современности, когда везде есть utf-8/utf-32, а стандартная библиотека (во всяком случае Си) хоть и поддерживает локализацию, но скорее наиболее неожиданными для программиста путями.
Но в случаях, когда локализация нужна, обычно локализируют и строки. В таким случае нам нужен gettext для локализации сообщений, ui тулкиты со встроенной локализацией, если мы работаем с gui/tui, unicode-утилиты для получения количества печатных символов, а не сырых кодпоинтов/байтов, если поставлена такая задача (что само по себе спорный вопрос т.к может не быть чёткого разделения для некоторых символов). А sprintf, который будет форматировать логи и технический вывод этим всем нагружать просто бессмысленно

std::locale

Пока что эта штука принесла мне кучу проблем вроде выкидывания исключений в неожиданных местах, поломок старых libc, ошибок сборки, но не помню ни одного случая, чтобы она была полезна

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

поддержка локалей здесь будет излишним усложнением

А sprintf, который будет форматировать логи и технический вывод этим всем нагружать просто бессмысленно

тоесть иными словами это лишь твоё субъективное мнение, а не «ненужная»?

Т.к эти функции используются для технических строк

это как? что такое «технические строки»

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

можно пример «неожиданных мест»? (просто я думаю ты почемуто оцениваешь вполне ожидаемые места для выброса исключений «неожиданными)

поломок старых libc, ошибок сборки

это как? как локаль могла „сломать“ libc?

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

думается необходимо формализовать «сложностность», а так же определить критериальностности отнесения к таковому

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

тоесть иными словами это лишь твоё субъективное мнение, а не «ненужная»?

обычно теримн «ненужно» в контексте ЛОРа являлся субъективным. Воспринимай, как удобнее

это как? что такое «технические строки»

Я же привёл примеры вроде логов или конфигов. Нужно точное определение?

можно пример «неожиданных мест»?

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

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

ранние конструкторы приложения

а это что еще за сущность? :)

но косвенно локали инициализирующего

что подразумевается под «косвенно» ?

и почему эти места кажутся тебе «неожиданными» ?

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

это как? что такое «технические строки»

Очевидно: те, которые не показываются юзеру в процессе штатной работы.

можно пример «неожиданных мест»?

Не знаю на счет исключений, но замена десятичной точки на запятую частенько оказывается неожиданной.

что подразумевается под «косвенно» ?

и почему эти места кажутся тебе «неожиданными» ?

Ну, например, gtk внезапно решил поменять локаль. А из-за этого основной ввод-вывод ломается.

COKPOWEHEU
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария