Пару логических задач для новичков)
| |
Нохчи | Дата: Вторник, 24 Апреля 2012, 15:47 | Сообщение # 21 |
заслуженный участник
Сейчас нет на сайте
| Да погляди же в что происходит отладчике или пошаговом режиме в студии.
Многие вопросы по Windows отпадут, если посмотреть тут
|
|
| |
vasua99 | Дата: Вторник, 24 Апреля 2012, 16:04 | Сообщение # 22 |
GNU follower
Сейчас нет на сайте
| Вот именно,что доступ к компу я временно не имею,а пользуюсь codepad.org. P.S я не юзаю студию,т.к работаю под линем,а винда для игр только
Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
|
|
| |
Тритон | Дата: Среда, 25 Апреля 2012, 08:21 | Сообщение # 23 |
постоянный участник
Сейчас нет на сайте
| Quote (Apati) т.к. если а и б в сумме превышают максимально допустимое значение для типа, то будет ошибка Вот именно. Поэтому этот способ требует сразу двух дополнительных переменных двойной разрядности. А что было в условии?
Добавлено (25.04.2012, 08:13) --------------------------------------------- Quote (vasua99) у мея есть предположение что при неявном преобразовани при вызове функции происходит дополнение до 4х Какое нафиг дополнение 5-ти до 4-х? Где ты нашёл преобразование? Где ты видишь хоть что то неявное? С какого перепугу что то вообще должно неявно дополняться? Явного же дополнения ты не написал.Добавлено (25.04.2012, 08:21) ---------------------------------------------
Quote (vasua99) короче смотри целый тип занимает 4 байта,а символ 1 байт, у нас есть строка (любая к примеру) тобишь массив символов.так вот при вызове функции обмена значениями (см выше) происходит неявное преобразование из ссылки на символ (который находится в массиве) в ссылку на целое.Но каким образом оно происходит? Символ тоже не вещественный. Целый - это просто целый, а не конкретный тип, под ним подразумеваются: signed small int, signed short int, signed long int, hyper, или их аналоги, char=signed small int. Где обязательное преобразование? я могу написать и так: Code void swap (char &x, char &y); char s[]="Hellow"; swap(s[0],s[4]); и строка не испортится. Кроме того, приведение к ссылке на другой размер вообще не возможно.
Не всё так плохо, как оно есть на самом деле.
Сообщение отредактировал Тритон - Среда, 25 Апреля 2012, 08:14 |
|
| |
Нохчи | Дата: Среда, 25 Апреля 2012, 08:31 | Сообщение # 24 |
заслуженный участник
Сейчас нет на сайте
| Тритон, дурачек, задолбал уже умничать. В функцию кстати два четырехбайтовых аргумента передается кстати(если х86).
Многие вопросы по Windows отпадут, если посмотреть тут
|
|
| |
Тритон | Дата: Среда, 25 Апреля 2012, 09:26 | Сообщение # 25 |
постоянный участник
Сейчас нет на сайте
| Ну да, адрес весит 4 байта. Но строка то весит 5 байт, не считая терминального ноля. Каким образом её можно дополнить до 4-х? А приведение к ссылке на другой размер не возможно, так как ссылка есть синоним и если это синоним байта, то он не может означать сразу 4. Так что это ты дурачок. Code small int a,b; swap (long int &a, long int &b); swap(a,b);// Ошибка, приведение не возможно , Code uint8_t a,b; swap (uint32_t &a, uint32_t &b); swap(a,b);// Ошибка, приведение не возможно , Code small int a,b; swap (long int a, long int b); swap(a,b);// Ошибки нет , Code uint8_t a,b; swap (uint32_t a, uint32_t b); swap(a,b);// Ошибки нет . Code small int a; std::cout<<sizeof(a); выведет 1, а не 4. На том же x86. Мало того, типы small int и char синонимичны, может быть только за исключением текстового ввода/вывода. Но small int - это как раз int.Quote (Нохчи) В функцию кстати два четырехбайтовых аргумента передается кстати Компилировать то пробовал, прежде чем обзываться? 1 байт нельзя передать по ссылке, если функция просит 4. Если int весит 4 байта, а char 1 байт, то такой вызов даже не скомпилируется, он не возможен. Если аргументы передаются по ссылке, а символы весят по одному байту, то в функцию можно передать только однобайтные аргументы. И вообще, к ссылке не приводят, если аргумент - ссылка, то передаётся адрес того, что есть без каких либо фактических преобразований. signed/unsigned может быть ещё приводится, но без фактического преобразования, простой заменой интерпретации значения, то есть приведение к signed портит большие значения, а к unsigned - отрицательные. Да и то надо проверить, приводится ли вообще. Code #include <cstdlib> #include <iostream> using namespace std; void swap222(int & a,int& b); int main(int argc, char *argv[]) { char str[] = "Hello"; swap222(str[0],str[4]); cout<<str; system("PAUSE"); } void swap222(int & a,int& b) { int t; t=a; a=b; b=t; } Quote Compiler: Default compiler <br /> Building Makefile: "C:\Projects\cpp\dev\Íîâàÿ ïàïêà\Makefile.win" <br /> Executing make... <br /> make.exe -f "C:\Projects\cpp\dev\Íîâàÿ ïàïêà\Makefile.win" all <br /> g++.exe -c main.cpp -o main.o -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"C:/Dev-Cpp/include/c++/3.4.2/backward" -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32" -I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include" <br /><br /> make.exe: *** [main.o] Error 1 <br /><br /> Execution terminated , Code #include <cstdlib> #include <iostream> using namespace std; void swap222(char & a,char& b); int main(int argc, char *argv[]) { char str[] = "Hello"; swap222(str[0],str[4]); cout<<str; system("PAUSE"); } void swap222(char & a,char& b) { char t; t=a; a=b; b=t; } вывело . Code #include <cstdlib> #include <iostream> using namespace std; void swap(int & a,int& b); int main(int argc, char *argv[]) { char str[] = "Hello"; swap(str[0],str[4]); cout<<str; system("PAUSE"); } void swap(int & a,int& b) { cout<<"!!!!"; } выводит тот же , но без 4-х восклицательных знаков, то есть void swap(int & a,int& b); не выполняется, а значит ни какие аргументы ей не передаются, выполняется же другая функция.Тот же результат даёт даже Code #include <cstdlib> #include <iostream> using namespace std; int main(int argc, char *argv[]) { char str[] = "Hellow"; swap(str[0],str[4]); cout<<str; system("PAUSE"); } , что указывает на то, что откуда то снаружи подцепилась функция swap (видимо стандартная), эти не сложные тесты показывают, что она swap(char&, char&); И ей передаются два однобайтных аргумента. Точнее два четырёхбайтных, но в них валяются только адреса однобайтных. Кстати, Нохчи, мне такой тест не нужен, кроме как для обнаружения готовой функции, мне хватает анализа, а ты на него не способен, что уже говорит о том, что дурачок именно ты. Так ты ещё и не смог оценить свои способности и не догадался провести тесты. А это уже говорит о психическом заболевании.
Не всё так плохо, как оно есть на самом деле.
Сообщение отредактировал Тритон - Среда, 25 Апреля 2012, 09:44 |
|
| |
vasua99 | Дата: Среда, 25 Апреля 2012, 12:36 | Сообщение # 26 |
GNU follower
Сейчас нет на сайте
| Тогда внимание вопрос:почему следующий код корректно работает(по крайне мере у меня компилит и работает правильно): Code void swap(int& a,int& b); char my[] = "Hello"; swap(my[0],my[4]); // !!! char& - > int& - как? printf("%s",my); // выводит oellH...
Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
|
|
| |
Нохчи | Дата: Среда, 25 Апреля 2012, 15:14 | Сообщение # 27 |
заслуженный участник
Сейчас нет на сайте
| Товарищу Тритону видимо совсем плохо стало, попробую объяснить на пальцах. В функцию однобайтовый аргумент передать вообще не возможно, даже если написать так: будет передан 4-байтовый аргумент, можете называть это дополнением до 4 байт или еще как-то. Это первое. Второе то, что Code void swap (char &x, char &y); char s[]="Hellow"; swap(s[0],s[4]); Таки испортит строку(читай #23). К чему эта лекция из #25 я не понял. В любом случае ничего дельного ты не сказал.
vasua99, вызывается не твоя функция swap.
Многие вопросы по Windows отпадут, если посмотреть тут
|
|
| |
Archido | Дата: Среда, 25 Апреля 2012, 15:29 | Сообщение # 28 |
Сэнсэй
Сейчас нет на сайте
| Омг, скока букаф
Quote (Тритон) Кроме того, приведение к ссылке на другой размер вообще не возможно.
Тритон, Проверяй:
Code void swap(int &a, int &b) { a ^= (b ^= (a ^= b & 0xFF) & 0xFF) & 0xFF; }
...
char str[] = "Hello"; swap((int&)str[0], (int&)str[4]);
C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)
Сообщение отредактировал Archido - Среда, 25 Апреля 2012, 15:30 |
|
| |
Matou | Дата: Среда, 25 Апреля 2012, 15:49 | Сообщение # 29 |
Исходный коТ
Сейчас нет на сайте
| Мой разум отказывается это воспринимать.
|
|
| |
Snuux | Дата: Среда, 25 Апреля 2012, 15:53 | Сообщение # 30 |
постоянный участник
Сейчас нет на сайте
| Quote (Matou) Мой разум отказывается это воспринимать. Аналогично...
|
|
| |
Нохчи | Дата: Среда, 25 Апреля 2012, 16:00 | Сообщение # 31 |
заслуженный участник
Сейчас нет на сайте
| Смотрим что будет дальше
Многие вопросы по Windows отпадут, если посмотреть тут
Сообщение отредактировал Нохчи - Среда, 25 Апреля 2012, 16:00 |
|
| |
vasua99 | Дата: Среда, 25 Апреля 2012, 18:12 | Сообщение # 32 |
GNU follower
Сейчас нет на сайте
| если вызывается не моя функция,то какая тогда?и еще одно - при таком же раскладе,у с указателями такая же байда?
Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
|
|
| |
Тритон | Дата: Четверг, 26 Апреля 2012, 15:29 | Сообщение # 33 |
постоянный участник
Сейчас нет на сайте
| Quote (vasua99) Тогда внимание вопрос:почему следующий код корректно работает(по крайне мере у меня компилит и работает правильно): Потому что есть ещё одна такая функция. Обмен , кстати, происходит в не зависимости не только от кода функции void swap(int& a,int& b);, но даже от факта её наличия/отсутствия, а код этой функции в любом случае не делает ничего. Кстати, наведи на аргумент в той стоке, где её вызываешь и тебе покажут правильный прототип void swap(T&, T&);, указывающий на то, что функция вообще шаблонная.
Добавлено (26.04.2012, 15:18) --------------------------------------------- Quote (Нохчи) В функцию однобайтовый аргумент передать вообще не возможно, Бред. В функцию Code void func(char x) { if (x==(char)0;) { return (char)1; } return x*func(x-1); } можно передать только однобайтный аргумент и ни какой другой. Так что всё зависит от самой функции.
Добавлено (26.04.2012, 15:21) --------------------------------------------- Quote (Нохчи) Таки испортит строку(читай #23). нет. до свапа s=={'H', 'e', 'l', 'l', 'o', 'w', '\0'}, после свапа s=={'o', 'e', 'l', 'l', 'H', 'w', '\0'}. Где порча?
Добавлено (26.04.2012, 15:24) --------------------------------------------- Quote (Archido) Тритон, Проверяй:
Code
void swap(int &a, int &b) { a ^= (b ^= (a ^= b & 0xFF) & 0xFF) & 0xFF; }
...
char str[] = "Hello"; swap((int&)str[0], (int&)str[4]); Про вторую функцию упорно забываем? Я же привёл тесты. Да и & 0xFF означает операцию AND с правым аргументом, приведённым к значению нужного размера. А если бы можно было привести к ссылке на больший размер, то ты бы вылез за границу конкретного данного. Что с массивами происходит при выходе за границу? В переменной просто нет места для лишних байтов и впихнуть их туда нельзя.
Добавлено (26.04.2012, 15:29) --------------------------------------------- Quote (vasua99) если вызывается не моя функция,то какая тогда?и еще одно - при таком же раскладе,у с указателями такая же байда? Читай стандарт, описание диалекта и все подключаемые головы. В одном из этих мест будет ещё один своп.
Не всё так плохо, как оно есть на самом деле.
Сообщение отредактировал Тритон - Четверг, 26 Апреля 2012, 15:30 |
|
| |
Archido | Дата: Четверг, 26 Апреля 2012, 15:49 | Сообщение # 34 |
Сэнсэй
Сейчас нет на сайте
| Тритон
Какая еще вторая функция? Так не пробовал сделать? Code void mycool_swap(int &a, int &b) { a ^= (b ^= (a ^= b & 0xFF) & 0xFF) & 0xFF; }
...
char str[] = "Hello"; mycool_swap((int&)str[0], (int&)str[4]); В функцию передается два 4-байтных Int'a, а не char'a и при чем именно по сылке - раз символы в массиве все таки меняются . В теле функции swap никаких приведений типов нет, так, что думай почему оно так
Quote (Тритон) Читай стандарт, описание диалекта и все подключаемые головы >> подключаемые головы
C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)
Сообщение отредактировал Archido - Четверг, 26 Апреля 2012, 15:51 |
|
| |
Тритон | Дата: Четверг, 26 Апреля 2012, 16:24 | Сообщение # 35 |
постоянный участник
Сейчас нет на сайте
| Quote (Archido) Какая еще вторая функция? Так не пробовал сделать? Code
void mycool_swap(int &a, int &b) { a ^= (b ^= (a ^= b & 0xFF) & 0xFF) & 0xFF; }
...
char str[] = "Hello"; mycool_swap((int&)str[0], (int&)str[4]);
В функцию передается два 4-байтных Int'a, а не char'a и при чем именно по сылке - раз символы в массиве все таки меняются . В теле функции swap никаких приведений типов нет, так, что думай почему оно так str={'H','e','l','l','o','\0'}, sizeof (str)=6. Code str: {'H','e','l','l','o','\0'} 1-й аргумент: X X X X 2-й аргумент: X X XX Выход за границу массива. Кстати, Code union { char x; hyper y; }; void f(hyper &y); x='q'; f(y);// Здесь нет выхода за границу, но даже это не приведение чара к ссылке на 8 байт (sizeof(hyper)=8), а порча данных. Привести к ссылке на другой размер не возможно вообще, на другой размер можно привести только к значению. Каким образом - это уже зависит от конкретной реализации оператора приведения, или приводящего конструктора. Бывает и дополнение полями, и дополнение единицами, и можно наворотить ещё много чего.
Не всё так плохо, как оно есть на самом деле.
Сообщение отредактировал Тритон - Четверг, 26 Апреля 2012, 16:41 |
|
| |
vasua99 | Дата: Четверг, 26 Апреля 2012, 16:25 | Сообщение # 36 |
GNU follower
Сейчас нет на сайте
| как вариант отследить адреса функций..)
Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
|
|
| |
Archido | Дата: Четверг, 26 Апреля 2012, 16:40 | Сообщение # 37 |
Сэнсэй
Сейчас нет на сайте
| Омг, скока я нового узнал то седня, особенно про "приводящие конструкторы" . А в своем примере ты ерунду написал.
Ты мне скажи - ты мой код пробовал запускать? Видел результат? Можешь объяснить почему оно так работает? (или будешь говорить - что не работает? ) . И еще раз повторюсь: в теле функции swap никаких приведений типов нет.
C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)
Сообщение отредактировал Archido - Четверг, 26 Апреля 2012, 16:40 |
|
| |
Тритон | Дата: Четверг, 26 Апреля 2012, 16:49 | Сообщение # 38 |
постоянный участник
Сейчас нет на сайте
| Quote (Archido) "приводящие конструкторы" ну если Code myclass { public: myclass (myclass &x); }; - копирующий, то как обозвать Code myclass { public: myclass (int &x); }; ? Подсказка: выполняется функцию не существующего оператора приведения Code class int { public: operator myclass (); }; .Добавлено (26.04.2012, 16:49) ---------------------------------------------
Quote (Archido) И еще раз повторюсь: в теле функции swap никаких приведений типов нет. Ты их воткнул в вызов. В явном виде. Но не привёл, а испортил. Символы переставятся сразу четвёрками, если за массивом есть другое данное, то полбеды, ты просто его запоганишь, а если там валяется функция, или память за массивом вообще не доступна приладе, то получишь крах с егогомессагой из системы. Привести же на другой размер нельзя. Значение можно, так как при этом создаётся новое значение уже другого данного, но в случае ссылки это должно быть то же самое данное.
Не всё так плохо, как оно есть на самом деле.
Сообщение отредактировал Тритон - Четверг, 26 Апреля 2012, 16:45 |
|
| |
Archido | Дата: Четверг, 26 Апреля 2012, 16:59 | Сообщение # 39 |
Сэнсэй
Сейчас нет на сайте
| Quote (Тритон) Ты их воткнул в вызов. В явном виде. Но не привёл, а испортил. Символы переставятся сразу четвёрками, если за массивом есть другое данное, то полбеды, ты просто его запоганишь, а если там валяется функция, или память за массивом вообще не доступна приладе, то получишь крах с егогомессагой из системы. Привести же на другой размер нельзя. Значение можно, так как при этом создаётся новое значение уже другого данного, но в случае ссылки это должно быть то же самое данное. . А вообще, чувак, ты мне нравишься, пиши еще!
Еще раз спрошу - ты смотрел результат выполнения кода? Вот тебе такое: Code void mycool_swap(int &a, int &b) { a ^= (b ^= (a ^= b & 0xFF) & 0xFF) & 0xFF; }
...
char str[] = "Hello bro"; mycool_swap((int&)str[0], (int&)str[4]); std::cout << str; Какой результат получается? Где и что тут портится? Жду новых историй
C++ - он особенный. С помощью него можно не только выстрелить себе в ногу, но и повеситься в пустой комнате:)
Сообщение отредактировал Archido - Четверг, 26 Апреля 2012, 17:00 |
|
| |
Тритон | Дата: Пятница, 27 Апреля 2012, 07:05 | Сообщение # 40 |
постоянный участник
Сейчас нет на сайте
| Хорошо, допустим строка у тебя длинная и за границу ты не выйдешь. Но функция то значение отдельного байта всё равно уже не способна ни прочитать, ни записать, так как он теперь зависим от соседних, а аргументы у тебя - байты. Уж если свопишь подстроки, то выглядеть это должно иначе. И тогда, понимая, что обрабатываешь данные другого размера, приводи внутри функции к блоку нужного размера, но подразумеваться то уже будет приведение 4-х символьной подстроки к двойному слову. Размер при этом уже совпадает. Речь то не о том, что нельзя хитрить с регистрами, а о том, что отдельный символ не приводится к ссылке на 4 символа. Если же "приводить", то получишь не ожиданные результаты и лишние сложности при чтении. Каждая строчка должна сама отражать решаемую задачу, а чтоб из mycool_swap((int&)str[0], (int&)str[4]); вытянуть задачу, придётся выполнить функцию и посмотреть результат. Хорошо, я способен выполнить её сам, но это относительно простой случай, а в более сложных остаётся пожелать удачного отладочного года, если не избавишься от подобного стиля. Так делать нельзя, это должно быть Code void swapby4(char &x, char &y) { uint32_t t; t=*(uint32_t *)(&x); *(uint32_t *)(&x)=*(uint32_t *)(&y); *(uint32_t *)(&x)=t; } , либо функция с этим же заголовком и телом из вставки на асме, если охота её оптимизировать. А ни как не то, что ты написал.
Не всё так плохо, как оно есть на самом деле.
Сообщение отредактировал Тритон - Пятница, 27 Апреля 2012, 07:09 |
|
| |
|