>>Компилятор на char все равно выделит int или даже больше, поскольку выравнивает
>
>Это определяется стандартом языка или архитектурой платформы?
>
>>по заданному размеру все переменные. Этот размер регулируется ключами компилятора. Тоесть
>>физически под 1 байтовую переменную будет выделено не менее 4 байт,
>>3 из которых никто никогда не использует. (На самом деле граница
>
>тогда по идее и отладчик должен показывать, что под переменную типа char
>выделено 32бита.Граница выравнивания определяется только установками компилятора. Выставить нужную границу интересно пользователю, и он для оптимизации выставляет ее равной разрядности платформы.
Смысл выравнивания заключается в том, чтобы ускорить операции с памятью. 32 битному процессору на чтение 32 битной ячейки памяти нужно меньше тактов, чем на чтение 16 или 8 битной ячейки памяти. Существует таблица ассемблерных команд с временами их выполнения.
Для 64 разрядного процессора, соответственно, проще работать с 64 разрядными ячейками.
Если при 64 битном выравнивании в памяти лежит объявленная переменная типа char, то скомпилированная программа физически будет читать-писать 64 бита, а использовать только младшие 8. Поэтому памяти физически выделится все-таки 64 бита.
Сам же компилятор будет искренне верить, что работает с 8 битами, поэтому sizeof честно вернет 1.
Вопрос выравнивания очень остро встает при межпроцессовом взаимодействии или при заполнении "строгих" таблиц, например таблиц файловой системы/MBR итд или таблиц-параметров к системным вызовам. Наверняка все с этим сталкивались.
>[оверквотинг удален]
>
>char j=6;
>
>(gdb) p j
>$1 = 6 '\006'
>(gdb) x/t &j
>0xbf955af3: 10010101010110110001000000000110
>(gdb)
>
>видно что крайние правые 8 бит отображают значение 6.
Я не знаком с gdb, а способов проверки могу представить сразу несколько. Только зачем это всё? В конечном итоге компилятор может от версии к версии различаться, или пользоваться какими-то своими соображениями по размещению данных в памяти. А ведь могут и параметры оптимизации влиять... Я сразу сказал, что эта теория - не есть абсолютная истина. Этих соображений придерживался компилятор от Интела, когда я этим интересовался. Логично и рационально. Я исхожу, что и другие компиляторы к этому стремятся, а там как знать... :)
Для проверки напиши что-ньть вроде
char a = 1; # 1
char b = 1; # 2
char c = 1; # 3
char d = 1; # 4
char e = 1; # 5
char find_me_in_dump = 2; # 6
char f = 1; # 7
char g = 1; # 8
А потом посмотри дамп памяти запущенного процесса. Можно еще содержимое бинарника посмотреть, узнать как всё лежит на харде. В обоих случаях надо искать двойку среди единиц. Конечно это простенький способ :) Тут компилятор может оказаться хитрее и соптимизировать что-ньть... Например не обратить внимания на переменные, которые в дальнейшем коде не используются.
Раз с дебагером знаком, то можно запросить на вывод 32 байта памяти, начиная с адреса переменной a. При выравнивании 1 байт двойка будет в шестом байте дампа. При выравнивании 4 байта двойка будет в шестом dword, в младшем байте. Нуитд.
>[оверквотинг удален]
>>
>>В твоем примере при вычислении "b + a" значение "а" и значение
>>"b" будут загружены в регистр процессора с приведением их к наиболее
>>широкому типу unsigned int в соответствии с условиями преобразования типов "Conditions
>
>ИМХО по стандарту он приведет их к int:
>
>"If an int can represent all values of the original type, the
>value is converted to an int; otherwise, it is converted to
>an unsigned int."
По второй ссылке в таблице условия в жестком порядке:
# If the preceding three conditions are not met, and if either operand is of type unsigned int, the other operand is converted to type unsigned int.
# If none of the preceding conditions are met, both operands are converted to type int.
Но ни в коем случае нельзя их считать руководством к действию, поскольку это компилятор микрософт и под винду. Тот самый ньюанс, когда ссылка на мсдн неуместна в качестве аргумента. Если есть подобное описание алгоритма, которого придерживается gcc, или стандарт си предполагает что-либо иное, то у микрософта последнее место в рейтинге доверия. Я эти ссылки написал просто потому что легче нагуглилось и в общем на вопрос отвечало :)
>В моем примере в тип int укладывается весь диапозон значений ориг. переменной -> значит приведение к int. Я не прав?
>
>То же самое в примере, представленном в http://msmvps.com/blogs/vandooren/archive/2007/10/05/integra...
>IMHO оба объекта преобразуются к int? Или это пример для С++ и
>там правила конверсии типов и преобразований другие?
Там нет беззнаковых переменных, не могу однозначно выразить свое имхо :)
К тому же приведение может зависеть от типа переменной, куда ляжет результат. Можно провести эксперименты:
1.
char a = -106; unsigned b = 2841417161;
int c = a + b;
2.
char a = -106; unsigned b = 2841417161;
unsigned int c = a + b;
3.
char a = 106; unsigned b = 2841417161;
int c = a + b;
4.
char a = 106; unsigned b = 2841417161;
unsigned int c = a + b;
Здесь в четырех примерах меняются два параметра:
тип результирующей переменной, чтобы понять играет ли она роль в приведении типов выражения,
и знак у знаковой переменной, чтобы по результату понять к чему ее привел компилятор при вычислении выражения.
У меня нет под рукой никакого компилятора, да и собственный опыт куда интереснее чем лекции слушать ;)
>>for Type Conversion" [2]. Разумеется, после вычисления unsigned int не уместится
>>в "char a" и получится варнинг о возможной потере данных при
>>присваивании результата.
>
>Очевидно, не все компиляторы предупреждают об этом, gcc c "-W -Wall -Wconversion"
>молчит, а вот splint ругается.
Ну вот, это как раз к вопросу о разных реализациях. Истина где-то рядом :))