@roens - это правильно. Это влияет на всех пользователей Anaconda, с ошибкой ниже curl: (77) error setting certificate verify locations:
CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
. Обходной путь заключается в использовании зависания системы по умолчанию и избегании возиться с добавленной переменной Anaconda PATH
. Вы можете либо
mv /path/to/anaconda/bin/curl /path/to/anaconda/bin/curl_anaconda
conda remove curl
$ which curl
/usr/bin/curl
[0] Anaconda Ubuntu curl Github issue https://github.com/conda/conda-recipes/issues/352
Выражение:
(expression1, expression2)
Первый expression1 оценен, тогда expression2 оценен, и значение expression2 возвращается для целого выражения.
Я видел, использовал больше всего в while
циклы:
string s;
while(read_string(s), s.len() > 5)
{
//do something
}
Это сделает операцию, затем сделает тест на основе побочного эффекта. Другой путь состоял бы в том, чтобы сделать это как это:
string s;
read_string(s);
while(s.len() > 5)
{
//do something
read_string(s);
}
Оператор запятой комбинирует эти два выражения любая сторона его в один, оценивая их обоих в слева направо порядке. Значение правой стороны возвращается как значение целого выражения. (expr1, expr2)
похож { expr1; expr2; }
, но можно использовать результат expr2
в вызове функции или присвоении.
Это часто замечается в for
циклы, чтобы инициализировать или поддержать несколько переменных как это:
for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
/* do something with low and high and put new values
in newlow and newhigh */
}
Кроме этого, я только использовал его "в гневе" в еще одном случае при оборачивании двух операций, которые должны всегда сочетаться в макросе. У нас был код, который скопировал различные двоичные значения в буфер байта для отправки в сети, и указатель поддержал, где мы имели до:
unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;
*ptr++ = first_byte_value;
*ptr++ = second_byte_value;
send_buff(outbuff, (int)(ptr - outbuff));
, Где значения были short
с или int
с, мы сделали это:
*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;
Позже мы читаем, что это не было действительно допустимым C, потому что (short *)ptr
больше не l-значение и не может быть увеличено, хотя наш компилятор в то время не возражал. Для фиксации этого мы разделяем выражение в два:
*(short *)ptr = short_value;
ptr += sizeof(short);
Однако этот подход полагался на всех разработчиков, не забывающих вставить оба оператора все время. Мы хотели функцию, куда Вы могли передать в выходном указателе, значении и и тип значения. Этот являющийся C, не C++ с шаблонами, у нас не могло быть функционального взятия произвольный тип, таким образом, мы обосновались на макросе:
#define ASSIGN_INCR(p, val, type) ((*((type) *)(p) = (val)), (p) += sizeof(type))
При помощи оператора запятой мы смогли использовать это в выражениях или как операторы, как мы желали:
if (need_to_output_short)
ASSIGN_INCR(ptr, short_value, short);
latest_pos = ASSIGN_INCR(ptr, int_value, int);
send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));
я не предполагаю, что любым из этих примеров является хороший стиль! Действительно, я, кажется, помню Steve McConnell Код, Завершенный отговаривание от ровного использования операторов запятой в for
цикл: для удобочитаемости и пригодности для обслуживания, циклом должны управлять только одна переменная и выражения в for
, сама строка должна только содержать управляющий код цикла, не другие дополнительные биты обслуживания цикла или инициализации.
Это вызывает оценку нескольких операторов, но использует только последний в качестве получающегося значения (rvalue, я думаю).
Так...
int f() { return 7; }
int g() { return 8; }
int x = (printf("assigning x"), f(), g() );
должен привести к x, устанавливаемому на 8.
Так же более ранние ответы указали, что это оценивает все операторы, но использует последний как значение выражения. Лично я только нашел его полезным в выражениях цикла:
for (tmp=0, i = MAX; i > 0; i--)
Единственное место я видел, что он полезен, - когда Вы пишете броский цикл, где Вы хотите сделать несколько вещей в одном из выражений (вероятно, init выражение или выражение цикла. Что-то как:
bool arraysAreMirrored(int a1[], int a2[], size_t size)
{
size_t i1, i2;
for(i1 = 0, i2 = size - 1; i1 < size; i1++, i2--)
{
if(a1[i1] != a2[i2])
{
return false;
}
}
return true;
}
Прощают мне, если существуют какие-либо синтаксические ошибки или если я смешался в чем-нибудь, что это не строгий C. Я не утверждаю, что, оператор является хорошей формой, но это - то, для чего Вы могли использовать его. В случае выше я, вероятно, использовал бы while
цикл вместо этого так, несколько выражений на init и цикле будут более очевидными. (И я инициализировал бы i1 и i2, встроенный вместо того, чтобы объявить и затем инициализировать.... и тому подобное.)