Russian Qt Forum

Программирование => С/C++ => Тема начата: OKTA от Февраль 13, 2014, 17:48



Название: Мелочь, но мало ли кто не знает)
Отправлено: OKTA от Февраль 13, 2014, 17:48
Уверен большинству это известно, но уверен, что есть и такие, кому нет, так что будет полезно) Вопрос, вобщем-то, вот в чем -
Что выдадут следующие команды:

Код:
printf("%d", sizeof("a"));
printf("%d", sizeof('a'));
printf("%d", sizeof(char));

А тут самопроверка) http://codepad.org/vy9jVYxA


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: Bepec от Февраль 13, 2014, 18:05
Ммм... не имел дела с printf уже давно :D
1) 8
2) 4
3) ?

Как же я ошибался :D поду веревку искать :D

Но в принципе ход мыслей был правильный :D


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: kambala от Февраль 13, 2014, 18:29
1. размер указателя (4 или 8 )
2. либо 1 либо 4 (не знаю приведется ли тут к инт)
3. 1


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: Bepec от Февраль 13, 2014, 18:47
Тут механику нужно знать :D


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: OKTA от Февраль 13, 2014, 19:14
Тут механику нужно знать :D
Что однако крайне полезно))


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: Bepec от Февраль 13, 2014, 19:16
В общем то у меня знание было, ток чуть замороченное ) В пропорциях совпадает, но вот тонкости :) Хотя тем не менее круто, потому что я использовал sizeOf года 4 назад в первый и последний раз :D


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: kambala от Февраль 13, 2014, 21:00
1. размер указателя (4 или 8 )
2. либо 1 либо 4 (не знаю приведется ли тут к инт)
3. 1
почти угадал (компилятор от студии-2012):
2 (почему?)
1
1


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: Kurles от Февраль 13, 2014, 21:04
почти угадал (компилятор от студии-2012):
2 (почему?)
в порядке бреда - размер самих данных, то есть 'a', 0x00?


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: Hellraiser от Февраль 13, 2014, 21:17
sizeof для типа данных вернет размер самого типа, поэтому sizeof(char) вернет 1. Для переменной sizeof возвращает размер занимаемой памяти (а не размер указателя). Поэтому sizeof("a") вернет 2 (не забываем про \0 в конце строки), а sizeof('a') вернет 1, т.к. это размер одного символа.


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: OKTA от Февраль 13, 2014, 21:23
а в Си sizeof('a') отдает 4, ибо операция '' немного иначе трактуется)


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: Bepec от Февраль 13, 2014, 22:07
Точнее современное sizeOf возвращает размер от char :D А указатель на данные  преобразуется в массив данных. MSDN форева.


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: Igors от Февраль 14, 2014, 15:44
2 (почему?)
Потому что "rvalue". Распишем так
Код
C++ (Qt)
char test[2] = ['a', 0];
При передаче в ф-цию (напр strlеn("a")) будет использован адрес, т.к. есть прототип ф-ции. Но для sizeof никаких указаний не было - ну он и вернет размер массива.


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: kambala от Февраль 14, 2014, 19:18
спасибо. Hellraiser, в общем-то, доступно расписал.


Название: Re: Мелочь, но мало ли кто не знает)
Отправлено: _Bers от Февраль 15, 2014, 20:03
Точнее современное sizeOf возвращает размер от char :D А указатель на данные  преобразуется в массив данных. MSDN форева.

printf("%d", sizeof("a"));

"a" - это не указатель на константу. Это - массив констант из двух элементов: 'a' и терминатор-нуль.
Он имеет тип const char[2];

sizeof(const char[2]) вернет 2, потому что размер массива - это размер типа элементов массива умноженное на количество элементов.


Тезис: литерные константы вида "trololo" имеют тип "массив констант типа char"

Доказательство:

Компилятор имеет право неявно приводить тип данных "массив" к типу данных "указатель". Но это не одно и тоже. Это два принципиально разные типы данных.

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

Обратите внимание на этот код:
http://rextester.com/IZG49875

Код:
//Title of this code

#include <iostream>
using namespace std;

template<size_t N>void View( const char (&a)[N] )
{
    cout<< "it is array\n";
    for( const auto& i: a)
        cout<< "item = "<< i<<endl;
}

template<size_t N>void View( const char* p )
{
    cout<< "it is pointer\n";
}


int main()
{
    cout << "Hello, world"<<endl;
    
    cout << typeid("Hello, world").name()<<endl;
    
    View("Hello, world");
}


Обратите внимание: есть две функции. одна принимает указатель, а другая - ссылку на массив.

Когда есть перегруженные функции, то компилятор в первую очередь выбирает ту, чей аргумент точно соответствует типу заявленной переменной.

И только если такой среди перегрузок нету, только тогда он пытается скастить тип заявленной переменной к типам аргументов прентендентов, и если какая то подойдет - выберет её.


Таким образом, если литерная константа "Hello, world" это массив, то должна запустится перегрузка, которая принимает ссылку на массив.

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

Как видите, запустилась версия с массивом. Следовательно литерная константа действительно имеет тип "массив констант типа char".

Тезис доказан.