Сумма трех байт
|
Пользователь Сообщения: 135 |
Профиль | Отправить PM | Цитировать Небольшая програмка на Си
Сумма трех байт: (Компилировалась на VC6) char buf[] = {1,4,16}; char *p= buf; int Sum1 = *(p++) + *(p++) + *(p++); p= buf-1; int Sum2 = *(++p) + *(++p) + *(++p); printf("Sum1=%d *** Sum2=%d\n", Sum1,Sum2); Цитата:
Цитата:
|
|||
Отправлено: 03:14, 25-09-2003 |
Старожил Сообщения: 167
|
Профиль | Отправить PM | Цитировать bilytur
Кофе попей, протри глаза, и внимательно посмотри, ЧТО ты складываешь: В первом случае ты складываешь, то что надо - buf[0]+buf[1]+buf[2] (p=buf) Во втором случае buf[-1]+buf[0]+buf[1] (p=buf-1 ) Так как buf[-1] имеет неопределённое значение, у тебя получаются разные результаты. Добавлено: bilytur Советую также обратить внимание (во избежание другого глюка) на то, что у тебя результат будет CHAR, а не INT, как ты хотел (если ты именно так хотел), возникнет переполнение. Чтобы этого избежать, надо написать int Sum1 = int(*(p++)) + *(p++) + *(p++); |
Отправлено: 04:20, 25-09-2003 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Старожил Сообщения: 240
|
Профиль | Отправить PM | Цитировать Sarge
Чё-то у тебя со знанием языка не того... Про постфиксные и префиксные операции слышал чего-нибудь? Сумма char-ов - действительно имеет тип char, н6о это если в арифметическом выражении не присутствуют операнды других типов, тогда будет сделано приведение типов. А здесь приведение производится при присваивании. Вопрос был почему написанное не даёт правильный результат? bilytur Трудно так сразу сказать. Я бы скомпилировал в ассемблер, и посмотрел, чё там VC имеет ввиду, обрабатывая этот текст. Там можно будет понять, когда он указатели продвигает, и на что они в тот момент указывают. Добавлено: А вообще C/C++ не любит таких наворотов. Он проводит оптимизацию при компиляции, а поскольку в выражении все операции равноправны, он может вычислять их в любом порядке, а не слева направо. И, казалось бы, да складывай их в любом порядке, они же одинаковые (операнды, я имею ввиду), но там ещё указатель перемещается, а это он как-то не очень любит. Так что, скомпили в ассемблер... |
------- Отправлено: 06:44, 25-09-2003 | #3 |
Новый участник Сообщения: 49
|
Профиль | Отправить PM | Цитировать Ассемблер рулез
Скомпилил твой пример и как оказалось в релизе сложения нет вообще. Вот сам код: push * *30h ; в десятеричном соответственно 48 push * *3 push * *offset aSum1DSum2D ; "Sum1=%d *** Sum2=%d\n" call * *sub_401014 ; это типа printf * Как видишь, никакого сложения нет. Компилятор сам вычислил значения Sum1 и Sum2 и заменил их вычисления уже числами... Удачи |
Отправлено: 12:20, 25-09-2003 | #4 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Тут дело в том, что порядок выполнения операций между точками следования не определён. Из фака su.c_cpp:
Цитата:
Кстати, так тоже нельзя писать: Т.е. нельзя ничего вычитать из адреса нулевого элемента массива. Это тоже может привести к гипотетическим граблям на некоторых архитектурах. (Например на x86 не в pmode, если у тебя массив лежит в самом начале сегмента, то будут проблемы). |
||
------- Отправлено: 17:29, 25-09-2003 | #5 |
Пользователь Сообщения: 135
|
Профиль | Отправить PM | Цитировать Большое спасибо всем.
ivank _Вам_ отдельный респект за полный и исчерпывающий ответ. |
Отправлено: 00:56, 26-09-2003 | #6 |
Старожил Сообщения: 167
|
Профиль | Отправить PM | Цитировать shurikan
1. Если тебе трудно сказать, то с твоим знанием СИ всё понятно. Я очень даже доходчиво написал, в чём проблема: p=buf-1 - во втором случае складываются не 0-й, 1-й и 2-й элемент массива, а -1-й, 0-й и 1-й ! А -1-й элемент может быть чем угодно, он не инициализирован. 2. Типы в проге приводятся уже ПОСЛЕ вычисления результата. Напиши такую прогу, например: unsigned char a=200, b=300; int c=a+b; Ты думаешь, что c=500 ?! Сначала вычислится результат с типом char, это 244 (переполнение через байт), а потом уже приведётся к типу int. unknown bug Ты немного выше по коду смотреть не пробовал? Это код printf и ВСЁ. Код сложения выше. |
Отправлено: 14:22, 27-09-2003 | #7 |
Модер Железа Сообщения: 1557
|
Профиль | Сайт | Отправить PM | Цитировать to Sarge
Я конечно извиняюсь, но проблемы с Си у Вас По тексту видно, что вторая строка (с Sum2) выдает правильный ответ, а первая -нет. Цитата:
Цитата:
Насчет кода - правда. Это код вызова функции printf, хотя кто знает, что там компилятор делает, оптимизируя код. Он так извращает код, что иногда оптимизацию приходится выключать [s]Исправлено: bgg0408, 2:45 28-09-2003[/s] |
||
------- Отправлено: 01:40, 28-09-2003 | #8 |
Пользователь Сообщения: 135
|
Профиль | Отправить PM | Цитировать Sarge Имхо, ты не прав.
Немного перепишем программку, чтоб она соответствовала Страуструпу. И введем char *p раньше, для того что-бы buf[] не лежал в начале сегмента на некоторых архитектурах Ты серьезно считаешь что это вычисляет buf[-1]+buf[0]+buf[1] чтоли? А переполнения в конкретном случае 1+4+16 тоже небыло. |
Отправлено: 02:25, 28-09-2003 | #9 |
Старожил Сообщения: 240
|
Профиль | Отправить PM | Цитировать Sarge
Неохота флеймить, но... Цитата:
Добавлено: Кстати, вспомни, как вычисляются выражения типа *(++p) и *(p++)... |
|
------- Отправлено: 03:08, 28-09-2003 | #10 |
Участник сейчас на форуме | Участник вне форума | Автор темы | Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Загрузка трех ОС на одном ПК | McLider | Хочу все знать | 1 | 10-01-2010 01:59 | |
Загрузка - меню загрузки трех операционных систем с трех HDD | sasa74 | Microsoft Windows 7 | 1 | 13-11-2009 20:34 | |
HDD - Неверная контрольная сумма ATA | vzh11 | Накопители (SSD, HDD, USB Flash) | 4 | 27-03-2009 17:28 | |
Мd5-сумма | Sviaga | Хочу все знать | 8 | 28-05-2008 19:41 | |
Байт и Бит | Apis.NET | Хочу все знать | 29 | 12-01-2002 21:32 |
|