Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.96/27: Рейтинг темы: голосов - 27, средняя оценка - 4.96
Заблокирован

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

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

Студворк — интернет-сервис помощи студентам
Пусть T - это некоторой тип, а t - это переменная типа T.
Может ли когда-нибудь выражение
C++
1
sizeof(T) != sizeof t
оказаться верным?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.11.2011, 11:53
Ответы с готовыми решениями:

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

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

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

39
Заблокирован
21.11.2011, 13:31  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Jupiter Посмотреть сообщение
по умолчанию то что в двойных кавычках имеет тип const char[](потому что мы не может написать вот так
C++
1
"TestStr" = ...
), а символьный массив а просто инициализируется строковым литералом
После чего мы уже ничего не можем записывать в этот массив (во всяком случае простым присваиванием типа
C++
1
a = "Best"
0
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
21.11.2011, 13:34
Цитата Сообщение от thick_int Посмотреть сообщение
После чего мы уже ничего не можем записывать в этот массив (во всяком случае простым присваиванием типа
присваивать строки нельзя, их можно только копировать, присваивать можно указатели на строковые литералы
1
Заблокирован
21.11.2011, 13:57
Цитата Сообщение от 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
4866 / 3287 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
21.11.2011, 22:28
Цитата Сообщение от thick_int
После чего мы уже ничего не можем записывать в этот массив
сделай a[0] = 'b';
0
Заблокирован
21.11.2011, 23:27  [ТС]
Цитата Сообщение от 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
Цитата Сообщение от 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
Заблокирован
21.11.2011, 23:59  [ТС]
А вот тут я тоже Вас хочу разочаровать.
Тот код, который вроде как не срабатывает
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
Цитата Сообщение от 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
4866 / 3287 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
22.11.2011, 01:03
Цитата Сообщение от 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
0 / 0 / 0
Регистрация: 14.01.2016
Сообщений: 8
14.01.2016, 19:03
Объясните нубу по поводу sizeof. В литературе данный оператор представлен как средство для обеспечения машинонезависимости, при этом указано, что оператор выполняется на этапе компиляции. Но если я получил ехе-файл на одной машине, а запустил на другой, то каким образом sizeof определит значения типов на новой машине? разве компиляция выполняется при каждом запуске ехе-файла?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
14.01.2016, 20:12
Цитата Сообщение от igelstein Посмотреть сообщение
Объясните нубу по поводу sizeof. В литературе данный оператор представлен как средство для обеспечения машинонезависимости, при этом указано, что оператор выполняется на этапе компиляции. Но если я получил ехе-файл на одной машине, а запустил на другой, то каким образом sizeof определит значения типов на новой машине? разве компиляция выполняется при каждом запуске ехе-файла?
что бы получить exe, нужно сначала скомпилировать программу.
после компиляции уже не существует ни sizeof, ни с++.

есть только машинный код - цепочка циферок,
которые понимает центральный процессор.
0
Неэпический
 Аватар для Croessmah
18150 / 10732 / 2067
Регистрация: 27.09.2012
Сообщений: 27,047
Записей в блоге: 1
14.01.2016, 20:15
Цитата Сообщение от igelstein Посмотреть сообщение
Но если я получил ехе-файл на одной машине, а запустил на другой, то каким образом sizeof определит значения типов на новой машине?
Никак. Ваша программа скомпилирована под определенную архитектуру.
0
0 / 0 / 0
Регистрация: 14.01.2016
Сообщений: 8
14.01.2016, 20:25
Цитата Сообщение от hoggy Посмотреть сообщение
что бы получить exe, нужно сначала скомпилировать программу.
после компиляции уже не существует ни sizeof, ни с++.
Цитата Сообщение от Croessmah Посмотреть сообщение
Никак. Ваша программа скомпилирована под определенную архитектуру.
Вот и я так же рассуждал. А причём тогда здесь машинонезависимость? Или это относится к компиляции в промежуточные "форматы"? когда программа "докомпелируется" при/перед выполнением в виртуальной среде или т.п.?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
14.01.2016, 21:20
Цитата Сообщение от igelstein Посмотреть сообщение
Вот и я так же рассуждал. А причём тогда здесь машинонезависимость?
при том, что программа компилируется конкретным компилятором под конкретную платформу.
а не в сферическом вакууме.

на разных платформах размеры типов могут быть разными.
но в исходном коде вам эти различия учитывать не нужно.

sizeof всегда возвращает правильный размер
независмо от платформы и её нюансов.
0
0 / 0 / 0
Регистрация: 14.01.2016
Сообщений: 8
14.01.2016, 21:56
hoggy, т.е. имеется в виду, что трансляция/компиляция проги на языке С++ будет давать идентичные результаты на разных машинах, но гарантированно работоспособными полученные/скомпилированные программы будут только на этих же машинах?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
14.01.2016, 22:42
Цитата Сообщение от igelstein Посмотреть сообщение
имеется в виду, что трансляция/компиляция проги на языке С++ будет давать идентичные результаты на разных машинах
нет.
результаты будут соотвествовать машинам
на которых осуществлялась сборка.
и могут не сооотвествовать другим машинам.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21287 / 8312 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
15.01.2016, 10:12
Цитата Сообщение от igelstein Посмотреть сообщение
Объясните нубу по поводу sizeof. В литературе данный оператор представлен как средство для обеспечения машинонезависимости, при этом указано, что оператор выполняется на этапе компиляции. Но если я получил ехе-файл на одной машине, а запустил на другой, то каким образом sizeof определит значения типов на новой машине? разве компиляция выполняется при каждом запуске ехе-файла?
В данном случае под словом "машиннонезависимость" на самом деле имеется в виду что-то типа "программные соглашения по размерам типов на конкретной платформе". Допустим, нужно обнулить массив. Если писать так:

C
int a[100];
memset (a, 0, 400);
то такой код будет работать правильно (т.е. по задумке афтора) только на тех платформах (точнее, компиляторах), где размер int'а равен 4 байтам. А если написать вот так:

C
int a[100];
memset (a, 0, 100 * sizeof(int));
то код будет работать корректно на любой платформе, на которой мы скомпилируем данный пример
0
Неэпический
 Аватар для Croessmah
18150 / 10732 / 2067
Регистрация: 27.09.2012
Сообщений: 27,047
Записей в блоге: 1
15.01.2016, 10:17
Evg, другими словами кроссплатформенность на уровне компиляции (исходного кода).
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21287 / 8312 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
15.01.2016, 12:03
Цитата Сообщение от Croessmah Посмотреть сообщение
кроссплатформенность
Кроссплатформенность - слишком широкое понятие. Тут даже не тянет на одну из её составляющих. Даже в рамках одного приложения на одной архитектуре полезно использовать sizeof. Типа того что

C
typedef int ttt;
ttt *p = malloc (n * sizeof (ttt));
или

C
typedef int ttt;
ttt *p = malloc (n * sizeof (*p));
Т.е. завели typedef, и работаем с ним через sizeof, чтобы не держать в голове реальный тип. Не говоря уж о том, что базовый тип typedef'а в какой-то момент может измениться

Добавлено через 2 минуты
Цитата Сообщение от thick_int Посмотреть сообщение
Пусть T - это некоторой тип, а t - это переменная типа T.
Может ли когда-нибудь выражение
sizeof(T) != sizeof t
оказаться верным?
Смотря что тут подразумевается под T: его синтаксическое написание или реальный тип переменной

C
#include <stdio.h>
 
void foo (int a[100])
{
  int b[100];
 
  printf ("%d\n", (int) sizeof(a));
  printf ("%d\n", (int) sizeof(b));
}
 
int main (void)
{
  foo (NULL);
  return 0;
}
Code
$ gcc t.c
$ ./a.out
4
400
Добавлено через 5 минут
Ну или для удобства вот так:

C
#include <stdio.h>
 
typedef int T[100];
 
void foo (T a)
{
  T b;
 
  printf ("%d\n", (int) sizeof(T));
  printf ("%d\n", (int) sizeof(a));
  printf ("%d\n", (int) sizeof(b));
}
 
int main (void)
{
  foo (NULL);
  return 0;
}
Code
$ gcc t.c
$ ./a.out
400
4
400
0
0 / 0 / 0
Регистрация: 14.01.2016
Сообщений: 8
15.01.2016, 15:14
Спасибо всем тем, кто помог советом и ответом. Свой затуп осознал
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.01.2016, 15:14

WriteProcessMemory нюансы использования
Доброго времени суток! Возникла такая проблема, при запуске проекта из VS2015 все компилируется, запускается и работает правильно, но когда...

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

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

Нюансы синтаксиса и тонкости использования указателей и массивов
Доброго времени суток! Никак не могу понять, почему один вариант кода работает: #include &lt;iostream&gt; #include &lt;stdlib.h&gt; ...

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


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации: 1. Вернуть возможность использования знаков | 1 l I;. . .
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
Генератор паролей (вариант №2)
Maks 30.10.2026
Обновленная версия ранее созданной обработки. Добавлены следующие реквизиты типа Булево: - Буквы; - Цифры; - Символы. Изменена логика команды "Сгенерировать" и процедуры "ПриОткрытии":. . .
Генератор паролей (вариант №1)
Maks 29.10.2026
Реализация из решения ниже выполнена исключительно по моей инициативе, дабы облегчить себе работу в создании паролей для администрируемых мною сервисов и пользователей. Самым главным критерием для. . .
Установка ChatGPT (Codex) на Windows без использования Microsoft Store
Fabien159 28.10.2026
Здравствуйте всем читающим! Опишу процесс установки ChatGPT (Codex) на Windows, если по каким-то причинам у вас не получается устанавить его через Microsoft Store. И так: 1. Скачиваем с. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru