Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 23, средняя оценка - 4.61
thick_int
Заблокирован
#1

Нюансы использования оператора sizeof() - C++

21.11.2011, 11:53. Просмотров 3021. Ответов 39
Метки нет (Все метки)

Пусть T - это некоторой тип, а t - это переменная типа T.
Может ли когда-нибудь выражение
C++
1
sizeof(T) != sizeof t
оказаться верным?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.11.2011, 11:53
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Нюансы использования оператора sizeof() (C++):

Нюансы использования оператора запятая или что такое UB и с чем его едят - C++
Почему студия и ideone выдают разные значения для a и b? в студии выходит a = 10 , b = 10 в ideone a = 20, b =10 #include...

Как корректно прервать цикл? (нюансы использования циклов, операторов ветвления и оператора break) - C++
Здравствуйте! такая форма работает...цикл нормально прерывается for(double i=1; i<=10; i++){ if(i==8) break; ...

Работа оператора Sizeof - C++
Каким образом вычисляется размер, допустим, массива int mass ? Где-то в памяти хранится размер, и оператор просто его оттуда вытаскивает,...

Объяснить нюансы использования литералов-перечислителей - C++
Почему в Си не допускается, чтобы один и тот же литерал-перечислитель входил в два различных перечислимых типа? Могут ли совпадать имена...

Нюансы использования операторов new/delete в деструкторах - C++
Подскажите пожалуйста, в чем проблема у меня в деструкторах? Есть 3 класса(по порядку размещения ниже), когда первые 2 удаляются все...

Нюансы синтаксиса и тонкости использования указателей и массивов - C++
Доброго времени суток! Никак не могу понять, почему один вариант кода работает: #include <iostream> #include <stdlib.h> ...

39
thick_int
Заблокирован
21.11.2011, 12:40  [ТС] #16
Понятно, спасибо.
Да были у меня какие-то сомнения то есть путаница между размером типа и длиной, ну например символьной строки.
0
Байт
Нарушитель
Эксперт C
16672 / 10933 / 1675
Регистрация: 24.12.2010
Сообщений: 21,309
21.11.2011, 12:42 #17
Если вы имеете в виду объем памяти, занимаемый объектом, вместе со всем, что выделено для него в куче, тогда безусловно вы правы. Но к sizeof это не имеет никакого отношения
1
accept
4828 / 3249 / 165
Регистрация: 10.12.2008
Сообщений: 10,569
21.11.2011, 12:58 #18
Цитата Сообщение от Net_Wanderer
accept, я не понял, что вы хотели сказать
то, на что указывает переменная-указатель, не имеет никакого отношения к содержимому переменной-указателя

здесь написано одно
здесь написано другое
0
thick_int
Заблокирован
21.11.2011, 13:11  [ТС] #19
А заодно поясниите еще такое затруднение:
Верно ли, что массив типа char (Пример
C++
1
char a[] = "Test"
), инициализированный строкой в стиле C в реальности имеет тип const char []? Во всяком случае ведет он себя именно так.
0
Jupiter
Каратель
Эксперт С++
6561 / 3982 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
21.11.2011, 13:28 #20
по умолчанию то что в двойных кавычках(строковый литерал) имеет тип const char[](потому что мы не может написать вот так
C++
1
"TestStr" = ...
), а символьный массив а просто инициализируется этим строковым литералом
0
thick_int
Заблокирован
21.11.2011, 13:31  [ТС] #21
Цитата Сообщение от Jupiter Посмотреть сообщение
по умолчанию то что в двойных кавычках имеет тип const char[](потому что мы не может написать вот так
C++
1
"TestStr" = ...
), а символьный массив а просто инициализируется строковым литералом
После чего мы уже ничего не можем записывать в этот массив (во всяком случае простым присваиванием типа
C++
1
a = "Best"
0
Jupiter
Каратель
Эксперт С++
6561 / 3982 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
21.11.2011, 13:34 #22
Цитата Сообщение от thick_int Посмотреть сообщение
После чего мы уже ничего не можем записывать в этот массив (во всяком случае простым присваиванием типа
присваивать строки нельзя, их можно только копировать, присваивать можно указатели на строковые литералы
1
Сыроежка
Заблокирован
21.11.2011, 13:57 #23
Цитата Сообщение от thick_int Посмотреть сообщение
Пусть T - это некоторой тип, а t - это переменная типа T.
Может ли когда-нибудь выражение
C++
1
sizeof(T) != sizeof t
оказаться верным?
Нет, не может! Память любому объекту всегда выдеяется на основании его типа. То есть, несколько косноязыча говоря, память выделяется типу, а затем предоставляется в распоряжение объекта.

Другое дело, что не всегда в выражениях можно заменить sizeof( T ) на siizeof( t ), хотя формально их значения равны.

Например,

C++
1
2
void f( int a, int b = sizeof( a ) );     //  Ошибка: нельзя использовать sizeof( a )
void f( int a, int b = sizeof( int ) );   //  Корректно: значение по умолчанию для параметра b = sizeof( int )
1
accept
4828 / 3249 / 165
Регистрация: 10.12.2008
Сообщений: 10,569
21.11.2011, 22:28 #24
Цитата Сообщение от thick_int
После чего мы уже ничего не можем записывать в этот массив
сделай a[0] = 'b';
0
thick_int
Заблокирован
21.11.2011, 23:27  [ТС] #25
Цитата Сообщение от accept Посмотреть сообщение
сделай a[0] = 'b';
Нет ну так то понятно. Однако и здесь не все так просто.
Например, вот такой вариант
C++
1
2
3
4
char str[5] = "Test";
cout << str << endl;
str[0] = 'B';
cout << str << endl;
проходит

И такой вариант
C++
1
2
3
4
char str[] = "Test";
cout << str << endl;
str[0] = 'B';
cout << str << endl;
тоже проходит

А вот такой уже не проходит
C++
1
2
3
4
char* str = "Test";
cout << str << endl;
str[0] = 'B'; //Здесь ошибка
cout << str << endl;
То есть в данном случае традиционная ассоциация между указателями и массивами слегка подпорчена.
0
Сыроежка
Заблокирован
21.11.2011, 23:51 #26
Цитата Сообщение от thick_int Посмотреть сообщение
Нет ну так то понятно. Однако и здесь не все так просто.
Например, вот такой вариант
C++
1
2
3
4
char str[5] = "Test";
cout << str << endl;
str[0] = 'B';
cout << str << endl;
проходит

И такой вариант
C++
1
2
3
4
char str[] = "Test";
cout << str << endl;
str[0] = 'B';
cout << str << endl;
тоже проходит

А вот такой уже не проходит
C++
1
2
3
4
char* str = "Test";
cout << str << endl;
str[0] = 'B'; //Здесь ошибка
cout << str << endl;
То есть в данном случае традиционная ассоциация между указателями и массивами слегка подпорчена.
Указатель - это не массив. Просто имеется неявное преобразование в выражениях или при передачи массива в качестве аргумента функции имени массива в указатель на его первый элемент.

В последнем вашем примере, вы объявляете указатель, который указывает на строковый литерал "Test". В С++ строковый литерал имеет тип const char[], поэтому и указатель правильно объявлять как

C++
1
const char *str = "Test";
Просто для совместимости с кодом языка С стандарт С++ разрешает не писать квалификатор const для таких указателей, хотя предупреждает, что в будущем такое послабление может быть отменено стандартом С++, а потому такое объявление указателя без const компиляторами будет рассматриваться как ошибка.
0
thick_int
Заблокирован
21.11.2011, 23:59  [ТС] #27
А вот тут я тоже Вас хочу разочаровать.
Тот код, который вроде как не срабатывает
C++
1
2
3
4
char* str = "Test";
cout << str << endl;
str[0] = 'B'; //Здесь ошибка
cout << str << endl;
на самом деле оказывается вполне работоспособным, если его оформить в виде отдельной функции и передать ей соответствующий указатель.
А вот если, объявить переменную str с типом const char*, то тут уже компилятор возмутится на передачу константного объекта в неконстантный параметр.
Ну в смысле, когда Вы менять будете.
Так что здесь иеются свои тонкости.
0
Сыроежка
Заблокирован
22.11.2011, 00:05 #28
Цитата Сообщение от thick_int Посмотреть сообщение
А вот тут я тоже Вас хочу разочаровать.
Тот код, который вроде как не срабатывает
C++
1
2
3
4
char* str = "Test";
cout << str << endl;
str[0] = 'B'; //Здесь ошибка
cout << str << endl;
на самом деле оказывается вполне работоспособным, если его оформить в виде отдельной функции и передать ей соответствующий указатель.
А вот если, объявить переменную str с типом const char*, то тут уже компилятор возмутится на передачу константного объекта в неконстантный параметр.
Так что здесь иеются свои тонкости.
Вы меня не разочаровали, потому что в отличии от вас я знаю стандарт С++!

Компилятору разрешается литералы помещать в память только для чтения. А потому если вы попытаетесь его изменить, то ваша программа может завершиться аварийно.
То есть попытка изменения строкового литерала согласно стандарту означает неопределенное поведение программы. Что это значит? Что, например, в Windows у вас программа завершится аварийно. А где-то в старом MS-DOS может и пройти такой фокус. Так что никаких "тонкостей" нет. Тонкости состоят лишь в том, что вы с первого раза не поняли, что я первоначально написал. Вот и вся "тонкость".
0
accept
4828 / 3249 / 165
Регистрация: 10.12.2008
Сообщений: 10,569
22.11.2011, 01:03 #29
Цитата Сообщение от thick_int
А вот такой уже не проходит
C++
1
2
3
4
char* str = "Test";
cout << str << endl;
str[0] = 'B'; //Здесь ошибка
cout << str << endl;
а с чего ему проходить ? указатель на символ и массив символов - разные вещи
в случае с указателем в него записывается один адрес одного символа, даже сам символ в него не записывается, только адрес
(адрес первого символа в цепочке символов, завершающейся нуль-символом, которая находится где угодно в памяти)

вот такая проходит
C++
1
2
3
4
5
char a[] = "Test";
char *str = a;
cout << str << endl;
str[0] = 'B'; //Здесь не ошибка
cout << str << endl;
0
igelstein
0 / 0 / 0
Регистрация: 14.01.2016
Сообщений: 4
14.01.2016, 19:03 #30
Объясните нубу по поводу sizeof. В литературе данный оператор представлен как средство для обеспечения машинонезависимости, при этом указано, что оператор выполняется на этапе компиляции. Но если я получил ехе-файл на одной машине, а запустил на другой, то каким образом sizeof определит значения типов на новой машине? разве компиляция выполняется при каждом запуске ехе-файла?
0
14.01.2016, 19:03
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.01.2016, 19:03
Привет! Вот еще темы с ответами:

Нюансы использования абстрактных базовых классов (класс Shape) - C++
У меня класс Point наследуется с абстрактного базового класса Shape, и Point тоже абстрактный, поскольку не определил функцию get_area()....

Объяснить нюансы использования указателей, массивов и ссылок в функциях - C++
Здравствуйте. Скажите, а что выводит arry значения элемента массива или его адрес? А как понимать что функция возвращает ссылку на int?...

Нюансы использования динамических массивов в качестве данных-членов в классах - C++
Здравствуйте! Не могу создать массив объектов. Помогите ... class hashTable { private: sortedlist* arr ; int arrSize; ...

Нюансы использования исключений: объяснить причины и способы устранения ошибки - C++
Есть такой кусочек кода. Я хочу просмотреть всё что хранится в операционной памяти. Ну и когда я пытаюсь посмотреть что у меня лежит по...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.