КИТА unofficial

Компьютерный => Программирование => Тема начата: LazarusLong от Март 15, 2007, 04:46:52



Название: Малоизвестные особенности С/С++
Отправлено: LazarusLong от Март 15, 2007, 04:46:52
Предлагаю писать сюда сабж.

1. Запись блока операторов в одну строку через запятую:
Оказывается запись:
{
 a=3;
 b=4;
 c=1;
}
Равносильна записи:
a=3, b=4, c=1;
При этом вся строка считается одним операторным блоком.

2. Можно еще и так:
float a = (flag?sin:cos)(x);
В данном случае результатом выполнения (flag?sin:cos) будет по видимому адрес вызваемой функции, которой передатся параметр (х).

3. Меняем индекс и массив местами
Имеем:
int a[10], i;

Обращения a[ i ] и i[a] - эквивалентны. Ведь на самом деле - a[ i ]==*(a+i)==*(i+a)==i[a]. От перемены мест слагаемых сумма не изменяется!



Название: Re: Малоизвестные особенности С/С++
Отправлено: grimgav от Март 15, 2007, 04:51:27
2. Можно еще и так:
float a = (flag?sin:cos)(x);
В данном случае результатом выполнения (flag?sin:cos) будет по видимому адрес вызваемой функции, которой передатся параметр (х).

3. Меняем индекс и массив местами
Имеем:
int a[10], i;

Обращения a[ i ] и i[a] - эквивалентны. Ведь на самом деле - a[ i ]==*(a+i)==*(i+a)==i[a]. От перемены мест слагаемых сумма не изменяется!

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


Название: Re: Малоизвестные особенности С/С++
Отправлено: Storm от Март 15, 2007, 06:34:36
за третий фокус надо по пятой точке бейсбольной битой давать, потому что этот фортиль скорее всего не переносимый. (как минимум может доставить головную боль, особенно при сложных моделях памяти)

первый еще более-менее полезно (условно)

второе конечно интересно, но с ифом проще и понятнее, а по коду не намного больше


Название: Re: Малоизвестные особенности С/С++
Отправлено: Alder от Март 15, 2007, 06:49:16
3. Меняем индекс и массив местами
Имеем:
int a[10], i;

Обращения a[ i ] и i[a] - эквивалентны. Ведь на самом деле - a[ i ]==*(a+i)==*(i+a)==i[a]. От перемены мест слагаемых сумма не изменяется!
А какой практический смысл этого?


Название: Re: Малоизвестные особенности С/С++
Отправлено: vimmax от Март 15, 2007, 06:58:43
Alder - я думаю практического смысла никакого, только теоретически показать возможность использования адресной арифметики в С, типа
a[ i ] равонсильно *(a+i)


Название: Re: Малоизвестные особенности С/С++
Отправлено: Sochin от Март 15, 2007, 07:25:03
Предлагаю писать сюда сабж.

1. Запись блока операторов в одну строку через запятую:
Оказывается запись:
{
 a=3;
 b=4;
 c=1;
}
Равносильна записи:
a=3, b=4, c=1;
При этом вся строка считается одним операторным блоком.

Да и более того, запятая это вообще отдельный оператор. Оператор «запятая» вычисляет все операнды, после этого отбрасывает результаты всех левых операндов. Результатом оператора «запятая» становится результат самого правого операнда, а типом - его тип.
Как и могие другие операторы оператор «запятая» можно перегрузить )))

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

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


Название: Re: Малоизвестные особенности С/С++
Отправлено: zer_owlet от Март 18, 2007, 10:47:13
гы )) когда Сная рассказал про третий фокус, я его пересказал у себя в офисе руководителю десктопного направления (у человека даже на знаю сколько лет опыта). он долго не верил. когда проверил - обзванивал своих знакомых, расказывал.... все были в шоке.


Название: Re: Малоизвестные особенности С/С++
Отправлено: Неудачник от Июнь 12, 2007, 01:55:13
int f1(int p1, int p2){};
int f2(int p1, int p2){};
int (f*)(int,int); // указатель на ф-цию
f=f1;
int r1=f(1,2); // вызываем f1
f=f2;
int r2=f(1,2); // вызываем f2
P.S. Спасибо за интересную тему! Выиграл много пива!!!


Название: Re: Малоизвестные особенности С/С++
Отправлено: LazarusLong от Июнь 12, 2007, 02:07:32
Вот еще подобный трюк. Может ли функция находится слева от оператора присваивания?

К примеру?
f() = 5;

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

int x;

int &f()
{
   return x;//Возврат ссылки на х.
}

main()
{
 f() = 5;
 cout << x;
 return 0;
}

Как несложно догадаться на экран выведется 5.


Название: Re: Малоизвестные особенности С/С++
Отправлено: tos от Декабрь 21, 2007, 05:44:41
обмен значений двух переменных
x ^= y ^= x ^=y
по скорости и объему машинного кода сильно проигрывает стандартному "tmp = x; x = y; y = tmp;", поэтому пользоваться не рекомендуется.


Название: Re: Малоизвестные особенности С/С++
Отправлено: EvilMax от Декабрь 21, 2007, 06:17:52
tos, а при чем тут особенности языка? Это задача-"баян" - поменять местами значения двух целочисленных переменных без использования третьей.


Название: Re: Малоизвестные особенности С/С++
Отправлено: tos от Декабрь 21, 2007, 06:23:44
ну трюк то прикольный.
такое мало кто знает поэтому пусть почитают про такие фичи.полезно ведь.


Название: Re: Малоизвестные особенности С/С++
Отправлено: Sochin от Декабрь 21, 2007, 06:25:04
tos

НО это не фича С++ как такового.


Название: Re: Малоизвестные особенности С/С++
Отправлено: tos от Декабрь 21, 2007, 06:28:42
а указатели на функцию есть и в ТРУПО ЛАСКАЛЕ!!!


Название: Re: Малоизвестные особенности С/С++
Отправлено: Sochin от Декабрь 21, 2007, 06:30:00
кто-то позиционировал указатели на функцию как фичу, впервые появившуюся и имеющую место быть только в С++?


Название: Re: Малоизвестные особенности С/С++
Отправлено: tos от Декабрь 21, 2007, 06:31:33

кто-то позиционировал указатели на функцию как фичу С++?
int f1(int p1, int p2){};
int f2(int p1, int p2){};
int (f*)(int,int); // указатель на ф-цию
f=f1;
int r1=f(1,2); // вызываем f1
f=f2;
int r2=f(1,2); // вызываем f2
P.S. Спасибо за интересную тему! Выиграл много пива!!!
ага!!!!некто НЕУДАЧНИК.


Название: Re: Малоизвестные особенности С/С++
Отправлено: LazarusLong от Декабрь 21, 2007, 06:32:47
Кстати можно написать довольно много решений этой задачи меняя только используемые операции (важно что бы операции были обратны друг-другу) к примеру +/-. Когда мне впервые эту задачку задали я придумал вообще вариант использующий умножение и деление, но я размышлял с точки зрения математики без привязки к конкретному языку :).


Название: Re: Малоизвестные особенности С/С++
Отправлено: Артем от Июль 11, 2008, 05:32:39
Увидил в примере из книги Павловской, жутко удивился, попробовал, работает  :o

Код:
#include <iostream.h>

void main()
{
  int a;
  cout<<a<<endl;

  a=int();
  cout<<a<<endl;

  a=float();
  cout<<a<<endl;
}

Результат:
Код:
1264
0
0


Название: Re: Малоизвестные особенности С/С++
Отправлено: Романыч от Июль 11, 2008, 05:58:14
Флуд почистил. Спор и все такое решаем через личку!
Романыч


Название: Re: Малоизвестные особенности С/С++
Отправлено: Alder от Июль 12, 2008, 11:43:39
Как программно определить, какой язык используется - С или С++?

Код:
#include <stdio.h>

int main ()
{
 printf ("%d\n", sizeof ('a'));
 return 0;
}

Для С результат будет равен 4, а для С++ 1. Проверялось на gcc/c++.
(Отправлено в: 12 Июля 2008, 11:42:06)
 C, Максимальное значение данного типа

Код:
unsigned max = ~0;


Название: Re: Малоизвестные особенности С/С++
Отправлено: Storm от Июль 14, 2008, 10:53:03
проверишь на 64 битной платформе - получишь 8 вместо 4 (на настоящей 64 бита типа UltraSparc). С преобразовал символ в число и в программме обработал целую переменную базового типа int. С++ обрабатывал как char - это скорее можно отнести к особенностям компиляторов, хотя стандарты на язык порыть не помешает, если это важно :)


Название: Re: Малоизвестные особенности С/С++
Отправлено: tos от Июль 14, 2008, 12:13:39
по моему дело не в самой платформе а в разрядности компилятора, не так ли?
например в VS есть компилятор x86-64


Название: Re: Малоизвестные особенности С/С++
Отправлено: Alder от Июль 14, 2008, 12:22:03
Storm, ну дык это и требовалось. Не особенности компилятора, а особенности самого языка получается. Т.е. для С++ мы получим 1, а для С не 1 :)


Название: Re: Малоизвестные особенности С/С++
Отправлено: Sochin от Июль 14, 2008, 04:45:28
Смотрим на отличия языков ISO C и C++, описанные в самом Стандарте С++:
Цитировать
Change: Type of character literal is changed from int to char
Rationale: This is needed for improved overloaded function argument type matching. For example:
int function( int i );
int function( char c );
function( ’x’ );
It is preferable that this call match the second version of function rather than the first.
Effect on original feature: Change to semantics of well-defined feature. ISO C programs which depend on
sizeof(’x’) == sizeof(int)
will not work the same as C++ programs.
Difficulty of converting: Simple.
How widely used: Programs which depend upon sizeof(’x’) are probably rare.
Про оператор sizeof:
Цитировать
The sizeof operator yields the number of bytes in the object representation of its operand.
...
sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1.
Стандарт С++ обязывает рассматривать символьный литерал как объект типа char, размер которого вне зависимости от реализации обязан быть равен одному.


Название: Re: Малоизвестные особенности С/С++
Отправлено: LazarusLong от Июль 29, 2012, 02:20:41
1. многие знакомы с тернарным оператором

x = (y < 0) ? 10 : 20;

но далеко не всем известно, что тернарный оператор может быть lvalue, т.е. находится слева от оператора присваивания:

(a == 0 ? a : b) = 1;

Что является сокращением для следующего кода:

if (a == 0)
    a = 1;
else
    b = 1;

2. в инициализационной части цикла for могут быть объявлены не только переменные но и классы, объекты, структуры, функции и т.д. Например

for(struct { int a; float b; } loop = { 1, 2 }; ...; ...) {
    ...
}