Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Почему странный результат при конвертации unsigned long x = (char)(128)? / 24 сообщений из 24, страница 1 из 1
02.11.2014, 07:00
    #38794137
jsa54513
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
Код: plaintext
1.
2.
char p = 128;
unsigned long l = p;



Лонг побитно получился такой:
Код: plaintext
1.
1000000011111111111111111111111111111111111111111111111111111111

Ну да, знаковое в беззнаковое конвертировать -- это конечно ербалайство, спору нет. Но всё равно интересно, как оно внутри так устроено, что так получается? Ведь если сделать unsigned char = char, то получилось бы 128, зачем в лонге единицы появились?
...
Рейтинг: 0 / 0
02.11.2014, 12:14
    #38794186
RWolf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
jsa54513,

На самом деле в p лежит число -128, потому что сработало приведение типов при присвоении (константа 128 не помещается в допустимый диапазон для signed char).
...
Рейтинг: 0 / 0
02.11.2014, 13:09
    #38794218
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
jsa54513зачем в лонге единицы появились?
Расширение знака.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
02.11.2014, 14:36
    #38794243
jsa54513
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
RWolfjsa54513,

На самом деле в p лежит число -128, потому что сработало приведение типов при присвоении (константа 128 не помещается в допустимый диапазон для signed char).
Это понятно.
...
Рейтинг: 0 / 0
02.11.2014, 14:36
    #38794244
jsa54513
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
Dimitry Sibiryakovjsa54513зачем в лонге единицы появились?
Расширение знака.

А зачем? Что за тупая операция?
...
Рейтинг: 0 / 0
02.11.2014, 15:17
    #38794254
Basil A. Sidorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
Затем, чтобы расширение знакового числа от меньшего к большему давало правильный результат.
...
Рейтинг: 0 / 0
02.11.2014, 16:14
    #38794278
jsa54513
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
Basil A. SidorovЗатем, чтобы расширение знакового числа от меньшего к большему давало правильный результат.
Так и получился неправильный результат.
...
Рейтинг: 0 / 0
02.11.2014, 16:18
    #38794279
Basil A. Sidorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
Это как считать.
Если беззнаковый байт со значением 128 рассматривать как знаковый, то получается -128.
...
Рейтинг: 0 / 0
02.11.2014, 16:39
    #38794287
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
jsa54513Так и получился неправильный результат.
А не надо было впихивать в char то, что в него не помещается :)
...
Рейтинг: 0 / 0
02.11.2014, 16:51
    #38794289
RWolf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
jsa54513,

Смотри, ты записал в signed char число -128. После этого ты присвоил его переменной unsigned long (диапазон допустимых значений 0…2 63 -1). Как компилятор должен обработать такой ход? Он поступает так: расширяет разрядность источника до 8 байт (диапазон -2 62 …2 62 -1), после чего забывает про знак, вот и получилось число с кучей единиц в старших битах.
...
Рейтинг: 0 / 0
05.11.2014, 03:02
    #38795703
SashaMercury
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
jsa54513
Ну да, знаковое в беззнаковое конвертировать -- это конечно ербалайство, спору нет.

Стандартом описано поведение в данном конкретном случае, и это не то слово что вы написали.

Вообще говоря, Anatoly Moskovsky дал вам уже правильный ответ.
Вы записали 128 в plain char, т.о. старший бит установили в 1, получите -128. Далее, если бы вы открыли стандарт языка Си, вы бы увидели в главе 6.3 Conversions следующее

ISO/IEC 9899:201x6.3 Conversions
1 Several operators convert operand values from one type to another automatically. This
subclause specifies the result required from such an implicit conversion, as well as those
that result from a cast operation (an explicit conversion). The list in 6.3.1.8 summarizes
the conversions performed by most ordinary operators; it is supplemented as required by
the discussion of each operator in 6.5.
2 Conversion of an operand value to a compatible type causes no change to the value or the
representation.
Forward references: cast operators (6.5.4).

и немного ниже

ISO/IEC 9899:201x6.3.1.3 Signed and unsigned integers
1 When a value with integer type is converted to another integer type other than _Bool, if
the value can be represented by the new type, it is unchanged.
2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or
subtracting one more than the maximum value that can be represented in the new type
until the value is in the range of the new type.60)
3 Otherwise, the new type is signed and the value cannot be represented in it; either the
result is implementation-defined or an implementation-defined signal is raised.

Думаю, в вашем случае нужно использовать пункт 2.
PS
Хотя, считаю что вашем случае, нужно остановиться на том, что вы записали в plain char 128.
...
Рейтинг: 0 / 0
05.11.2014, 03:59
    #38795708
jsa54513
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
RWolfjsa54513,

Смотри, ты записал в signed char число -128. После этого ты присвоил его переменной unsigned long (диапазон допустимых значений 0…2 63 -1). Как компилятор должен обработать такой ход? Он поступает так: расширяет разрядность источника до 8 байт (диапазон -2 62 …2 62 -1), после чего забывает про знак, вот и получилось число с кучей единиц в старших битах.
Спасибо, я понял. Ключевой момент: он расширяет ещё до убирания знака.
...
Рейтинг: 0 / 0
05.11.2014, 04:15
    #38795709
SashaMercury
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
jsa54513RWolfjsa54513,

Смотри, ты записал в signed char число -128. После этого ты присвоил его переменной unsigned long (диапазон допустимых значений 0…2 63 -1). Как компилятор должен обработать такой ход? Он поступает так: расширяет разрядность источника до 8 байт (диапазон -2 62 …2 62 -1), после чего забывает про знак, вот и получилось число с кучей единиц в старших битах.
Спасибо, я понял. Ключевой момент: он расширяет ещё до убирания знака.

никакого убирания знака не происходит в принципе. Ни до, ни после, ни вообще.
...
Рейтинг: 0 / 0
06.11.2014, 07:02
    #38796903
SashaMercury
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
jsa54513,

сегодня утром я разминался, и решал простую задачу .
Посмотрите пожалуйста на код ниже.


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
int factorial(int n)
{
	int res = 1;
	for (int i = 2; i <= n; ++i)
	{
		res *= i;
	}
	return res;
}

long long int get_count_variants(int n, int k)
{
	long long int res = 0;
	if (n < k)
	{
		//nothing do
	}
	else if (k == 1)
		res = n*n;
	else if (n == k)
		res = factorial(n);
	else
	{
		res = 1;
		for (int i = 0; i <k; ++i)
		{
			res *= n*n - 2 * n*i + i*i;
		}
		printf("%i %i\n", res, n);
		printf("%i %i\n", n, res);
		res /= factorial(k);
	}
	return res;
}



Как вы считаете, есть ли в нём ошибка(в выделенных строчках), что будет отправлено на поток вывода, и почему ? На вход отправим 7 и 2, например. (также, я вас не прошу, но не буду возражать, если вы предложите оптимальный алгоритм,)
...
Рейтинг: 0 / 0
06.11.2014, 14:55
    #38797356
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
SashaMercuryjsa54513,

сегодня утром я разминался, и решал простую задачу .
Посмотрите пожалуйста на код ниже.


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
int factorial(int n)
{
	int res = 1;
	for (int i = 2; i <= n; ++i)
	{
		res *= i;
	}
	return res;
}

long long int get_count_variants(int n, int k)
{
	long long int res = 0;
	if (n < k)
	{
		//nothing do
	}
	else if (k == 1)
		res = n*n;
	else if (n == k)
		res = factorial(n);
	else
	{
		res = 1;
		for (int i = 0; i <k; ++i)
		{
			res *= n*n - 2 * n*i + i*i;
		}
		printf("%i %i\n", res, n);
		printf("%i %i\n", n, res);
		res /= factorial(k);
	}
	return res;
}



Как вы считаете, есть ли в нём ошибка(в выделенных строчках), что будет отправлено на поток вывода, и почему ? На вход отправим 7 и 2, например. (также, я вас не прошу, но не буду возражать, если вы предложите оптимальный алгоритм,)

Ошибка есть. Формат в printf должен соответствовать типу и размеру данных, передаваемых в соотв. параметре, либо нужно при передачи делать явное преобразование данных.

Код: plaintext
1.
2.
3.
printf("%lli %i\n", res, n);
// or
printf("%i %i\n", (int)res, n);



Что будет отправлено в поток вывода, если это не сделать, не определено языком, а по сути в зависимости от endianness будет напечатана какая-то часть байтов числа в виде целого со знаком, либо если переданное меньше по размеру -- какой-то случайный мусор в виде числа, т.е. просто будет напечатана какая-то хрень.
...
Рейтинг: 0 / 0
06.11.2014, 15:59
    #38797434
SashaMercury
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
В моём случае res напечатался нормально, а вот вместо n выводился 0. Это в первой строчке. А во второй всё нормально (касаемо вывода)
...
Рейтинг: 0 / 0
06.11.2014, 16:04
    #38797442
SashaMercury
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
Потому уточню, это undefined behaviour или implementation-defined behavior ? (стандарта нет под рукой)

То что проблема в том, что неправильно указан спецификатор вывод я понял. Далее, мне казалось, что в первом случае переменная res затирает "значение" n "непрочитанными байтами".
Но моё объяснение не совпадает с вашим, потому видимо я ошибаюсь
...
Рейтинг: 0 / 0
06.11.2014, 16:49
    #38797506
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
SashaMercuryВ моём случае res напечатался нормально, а вот вместо n выводился 0. Это в первой строчке. А во второй всё нормально (касаемо вывода)


"res напечатался нормально" -- это частный случай более общего "напечатает какую-то хрень".
...
Рейтинг: 0 / 0
06.11.2014, 16:50
    #38797509
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
Это undefined behaviour
...
Рейтинг: 0 / 0
06.11.2014, 17:02
    #38797524
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
SashaMercuryПотому уточню, это undefined behaviour или implementation-defined behavior ? (стандарта нет под рукой)

То что проблема в том, что неправильно указан спецификатор вывод я понял. Далее, мне казалось, что в первом случае переменная res затирает "значение" n "непрочитанными байтами".
Но моё объяснение не совпадает с вашим, потому видимо я ошибаюсь

В общем случае технически что происходит --
при вызове в стек кладутся одна за другой две переменные (значения их, естественно), двух типов (в соотсветствии с объявлением переменных), одна за другой, в порядке, определённом соглашением о вызовах.
Затем printf этот набор байт из содержимого двух переменных (и возможно байт для выравнивания между ними) интерпретируется
в соответствии с соглашением о вызовах функций и типами параметров, указанных в форматной строке, и оттуда выуживаются значения для подстановки в формат.
...
Рейтинг: 0 / 0
07.11.2014, 01:53
    #38798018
SashaMercury
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
MasterZivSashaMercuryПотому уточню, это undefined behaviour или implementation-defined behavior ? (стандарта нет под рукой)

То что проблема в том, что неправильно указан спецификатор вывод я понял. Далее, мне казалось, что в первом случае переменная res затирает "значение" n "непрочитанными байтами".
Но моё объяснение не совпадает с вашим, потому видимо я ошибаюсь

В общем случае технически что происходит --
при вызове в стек кладутся одна за другой две переменные (значения их, естественно), двух типов (в соотсветствии с объявлением переменных), одна за другой, в порядке, определённом соглашением о вызовах.
Затем printf этот набор байт из содержимого двух переменных (и возможно байт для выравнивания между ними) интерпретируется
в соответствии с соглашением о вызовах функций и типами параметров, указанных в форматной строке, и оттуда выуживаются значения для подстановки в формат.

Примерно так я и представлял. В моём случае res помещалось в 4 байта, потому чтение/вывод в поток произошли нормально.(как вы выше сказали, это всего-лишь частный случай), далее при чтение следующих 4 байт, была прочитана не память n, а был затронут остаток непрочитанных байт от res. Вот так я думал. Такое поведение возможно ?

А во втором случае, такого не происходит, потому что первой читается n, а уже потом res
...
Рейтинг: 0 / 0
07.11.2014, 02:46
    #38798035
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
SashaMercuryПримерно так я и представлял. В моём случае res помещалось в 4 байта, потому чтение/вывод в поток произошли нормально.(как вы выше сказали, это всего-лишь частный случай), далее при чтение следующих 4 байт, была прочитана не память n, а был затронут остаток непрочитанных байт от res. Вот так я думал. Такое поведение возможно ?
Только уточнение.
long long (значит и res) занимает 8 байтов.
int занимает 4 байта.

Для printf (как и для любых других функций с ... в прототипе) передача параметром long long выглядит так же как и передача двух int.
Причем порядок в котором она видит эти два виртуальных int зависит от порядка байтов/слов платформы.
На интеле (little-endian) младшая половина res будет первым, старшая - вторым.
На других платформах может быть по-другому.

Кроме того надо понимать, что printf в принципе не может определить количество и размер переданных параметров.
Поэтому она смотрит на строку формата, а про следующие параметры, неописанные в формате она ничего не знает и игнорирует.
...
Рейтинг: 0 / 0
07.11.2014, 06:50
    #38798095
SashaMercury
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
Хорошо

у меня оставался только вопрос, как он читает, слева направо, или наоборот, вы на него уже ответили :)
...
Рейтинг: 0 / 0
07.11.2014, 07:04
    #38798096
SashaMercury
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему странный результат при конвертации unsigned long x = (char)(128)?
Anatoly Moskovsky,
причём когда столкнулся с этой проблемой, то сначала разобрался в ней(первоначально я не понял в чём дело), а уже потом рассказал про неё :)

PS
Правда я думал что это будет больше интересно автору топика, он ведь разбирался в типом данных long, а он куда-то пропал
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Почему странный результат при конвертации unsigned long x = (char)(128)? / 24 сообщений из 24, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]