Язык Си. Выражения

Выражения в языке Си. Обобщенный блог. В целом о выражениях.

Источник информации - ISO/IEC 9899:201x

Выражения(expressions) это последовательность операторов и операндов, результатом вычисления которого есть некое значение, или то что описывает объект или функцию, или комбинация операторов операндами которых являются переменные, функции, литералы...
  int array[] = {1, 2, foo(3)};
  i++;
  i = ++i + 90;
  i = foo(i) / 2;
  foo(i * 2);

Есть такое понятие как побочный эффект(side effect) для выражений. Побочный эффект это - любые инструкции вследствии работых которых изменяются глобальные(статические) объекты, объекты с модификатором volatile, изменяются файлы, меняются аргументы функций, генерится исключение.

Порядок выполнения выражений не определен, если в выражении присутствует изменение одного объекта больше чем один раз.
Нельзя однозначно сказать каким будет результат примера ниже.
  int i = 0;
  i = ++i + ++i;
У меня это 4, но на это компилятор выдает предупреждение - warning: operation on ‘i’ may be undefined.
Нужно избегать всех этих выражений, лучше разбить одно такое сложное выражение на 2-3 простых выражения, взглянув на которые вы сможете однозначно, ответить каким будет результат.

Такие операторы как - унарный(~) , и бинарные(<<, >>, &, ^, | )  называются битовыми операторами. Операндами для этих операторов должны быть переменные с целочисленным типом.

Когда в результате выполнения выражения происходит исключительное событие(к примеру нельзя что-то вычислить математически, или выход за пределы массивов, или еще что-то), то результат поведения программы не определено. Поэтому нужно контролировать самим возможные исключительные ситуации.

Массивы.
Запись E1[E2] идентична записи ( *( (E1) + (E2) ) ). E1 - это массив(что означает указатель на первый элемент массива), E2 - это целочисленное значение. Соответственно к указателю прибавляется целочисленное значение(происходит смещение адреса на - указанное количество байт, количество байт вычисляется просто, берется это целочисленное значение(E2) и умножается на размер типа данных которые хранятся в массиве), и мы получаем доступ к элементу массива E1 по индексу E2. 
Запись int x[3][5]; означает объявление двумерного массива 3 на 5, то есть x является массивом из трех элементов каждый из которых является массивом из пяти элементов. Запись x[i]  эквивалентна ( *( (x)+(i) ) ), x является указателем на первый массив(из трех элементов), прибавляя к этому  указателю i, в результате мы получаем указатель на второй массив. Запись x[i][j] эквивалентна *( ( ( (int*)(x) + i * array_columns ) ) + j ), где array_columns количество колонок, то есть вторая размерность массива, в данном случае 5.

Функции.
void foo(int a, char b)
{
}

foo_a(1, '1');
В первой записи, объявление и определение функции с именем foo_a.
(int a, char b) - являются параметрами функции.
foo_a(1, '1') называется вызовом функции с аргументами 1 и '1'. Аргументами функции могут быть любые выражения законченного типа. Перед вызовом функции, все аргументы вычисляются, и только потом вызывается функция с известными значениями аргументов.
Если количество агрументов, не равно количеству параметров, поведение не определено.
Для объявления функций с неизвестным количеством параметров, к примеру по типу функции printf() используйте следующую запись:
void my_printf(char *pFormat, ...)
{
}
В этом случае количество аргументов вычисляется по входящей строке, либо же, вместо этого можно первым параметром передавать количество аргументов, соответственно нужно изменить тип, сhar* на int. Для того чтобы извлечь все аргументы, нужно использовать макросы va_list, va_start, va_arg, va_end.

Порядок вычисления выражений в аргументах функций, не определен. Все побочные эффекты должны быть выполнены перед фактическим вызовом функции.
  foo( f1(), f2(), f3());
В примере выше, порядок выполнения функций не определен, они могут быть выполнены в таком порядке - f1(), f2(), f3() или же в обратном. После того как все выражения в аргументах будут вычислены, будет вызвана функция foo().

Структуры и объединения.
Для доступа к членам структуры или объединения используется 2 вида операторов -  точка(.) и -> . 
Точка используется если первым операндом является объект типа структуры или объединения, второй операнд это имя члена структуры или объединения этого типа.
-> используется если первым операндом является указатель на объект типа структуры или объединения, второй операнд это имя члена структуры или объединения этого типа.
typedef struct
{
  int a;
}s;

int main()
{
  s _s;
  s *_ps;
  _s.a = 0;
  _ps->a = 0;
  return 0;
}
Если функция возвращает объект типа структуры или объединения, принцип обращения остается таким же, foo().a или pfoo()->a .
Оператор взятия адреса, приводит операнд к указателю на этот операнд
typedef struct
{
  int a;
}s;

int main()
{
  s _s;
  (&s)->a = 0;
  return 0;
}

!!ДОПОЛНЯЕТСЯ!!








Комментарии

  1. ВСЕ ПРОЧИТАЙТЕ НАСТОЯЩЕЕ ОТЗЫВ О том, КАК Я ПОЛУЧИЛ СВОЙ КРЕДИТ ОТ КОМПАНИИ LEGIT И ДОВЕРЕННОЙ КРЕДИТНОЙ СРЕДИ Меня зовут Kjerstin Lis, я искал кредит для погашения своих долгов, все, кого я встречал, мошенничали и брали свои деньги, пока я наконец не встретил мистера Бенджамина Брейл Ли Он смог дать мне кредит в размере 450 000 рублей. Он также помог другим моим коллегам. Я говорю как самый счастливый человек во всем мире сегодня, и я сказал себе, что любой кредитор, который спасает мою семью от нашей бедной ситуации, я скажу имя всему миру, и я так счастлив сказать, что моя семья вернулся навсегда, потому что я нуждался в кредите, чтобы начать свою жизнь заново, потому что я одинокая мама с 3 детьми, и весь мир, казалось, висел на мне, пока я не имел в виду, что БОГ послал ссудодателя, который изменил мою жизнь и член моей семьи, БОЖИЙ кредитор, мистер Бенджамин, он был Спасителем БОГом, посланным для спасения моей семьи, и сначала я подумал, что это будет невозможно, пока я не получу кредит, я пригласил его к себе в семью -все вечеринка, от которой он не отказался, и я посоветую всем, кто действительно нуждается в кредите, связаться с г-ном Бенджамином Брейлом Ли по электронной почте (lfdsloans@outlook.com), потому что он самый понимающий и добрый кредитор. когда-либо встречал с заботливым сердцем. Он не знает, что я делаю это, распространяя свою добрую волю ко мне, но я чувствую, что должен поделиться этим со всеми вами, чтобы освободить себя от мошенников, пожалуйста, остерегайтесь подделок и свяжитесь с правильной кредитной компанией. com или whatsapp + 1-989-394-3740. ,

    ОтветитьУдалить

Отправить комментарий