Linux.org.ru
Новости - Галерея - Форум - Трекер - Wiki - Поиск
[#]  
jtootf (фотография)

[C++] почему?

void f(const int[3]); 
 
... 
 
f({1, 2, 3});

почему так нельзя? при том, что вот так:

const int a[3] = {1, 2, 3}; 
 
f(a);

вполне себе законно. {} - это, вроде бы, конструктор для const T[]; конструкторы в вызове функции использовать вполне себе можно. основание для такого особого отношения есть вообще?

это всё при том, что:

void g(const char[3]); 
 
... 
 
g("123");

замечательно работает. C-style строка в C++ - она, в общем-то, массив символов - два исключения из общих языковых правил в одном выражении

ну и то, что и в f и в g можно с лёгкостью передавать массивы большего размера, чем указано в сигнатуре, тоже как-то нехорошо. приведение T[] к T* это, конечно, не так уж и плохо - но толку тогда от такой сигнатуры, спрашивается, если компилятор (с -Wall -pedantic) даже предупреждения не выдаёт?

jtootf ** (27.10.2009 2:37:50)

[#] Ответ на: [C++] почему? от jtootf 27.10.2009 15:11:00  

Re: [C++] почему?

>про f((int[3]){1, 2, 3})

тут тип известен. хотя насколько это соответствует стандарту, судить не берусь.

anonymous (27.10.2009 15:17:28)
[#] Ответ на: [C++] почему? от Absurd 27.10.2009 15:06:07  

Re: [C++] почему?

>>Взять адрес у несуществующего массива реально трудно.

> Он вполне себе существует в рантайме в секции .const вместе с другими литералами.


Нет гарантии существования литерных констант в рантайме.

int a;
a = a + 1;

"1" - литерная константа, но ни в сеции .const, ни где бы то нибыло еще ее может не оказаться. Достаточно очевидно, что взять адрес у литерной константы на этапе компиляции нельзя, и добавленный воркэраунд для "string literal" не отменяет этого общего правила.

LamerOk ** (27.10.2009 15:26:00)
[#] Ответ на: Re: [C++] почему? от LamerOk 27.10.2009 15:26:00  

Re: [C++] почему?

> int a;
> a = a + 1;


Подразумевается

int a;
...
a = a + 1;

LamerOk ** (27.10.2009 15:28:13)
[#] Ответ на: Re: [C++] почему? от LamerOk 27.10.2009 15:26:00  
jtootf (фотография)

[C++] почему?

>добавленный воркэраунд для "string literal" не отменяет этого общего правила

чем этот воркэраунд не подходит для общего случая?

jtootf ** (27.10.2009 15:30:36)
[#] Ответ на: Re: [C++] почему? от LamerOk 27.10.2009 15:26:00  

Re: [C++] почему?

>добавленный воркэраунд для "string literal" не отменяет этого общего правила.

с чего он стал "воркэраунд"? ведь в этом случае указатель в рантайме передают( а не само значение), который должен указывать на объект.

anonymous (27.10.2009 15:32:21)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 15:30:36  

[C++] почему?

Вопросы к Д. Ритчи.

LamerOk ** (27.10.2009 15:51:51)
[#] Ответ на: [C++] почему? от LamerOk 27.10.2009 15:51:51  
jtootf (фотография)

[C++] почему?

>Вопросы к Д. Ритчи.

ну вот, чуть что так сразу к Ритчи; неужели на ЛОРе не хватит аналитиков, чтобы ответить на этот вопрос?

jtootf ** (27.10.2009 15:53:12)
[#] Ответ на: Re: [C++] почему? от anonymous 27.10.2009 15:32:21  

[C++] почему?

С того, что этот синтаксис ортогонален синтаксису любых других константных литералов во время компиляиции и введен с единственной целью - не превращать объявление обычных строк в священную процедуру с бубуном. И, сделав это исключение, всё таки напоролись на грабли с const, приведенные выше.

LamerOk ** (27.10.2009 15:54:36)
[#] Ответ на: [C++] почему? от LamerOk 27.10.2009 15:54:36  
jtootf (фотография)

[C++] почему?

>не превращать объявление обычных строк в священную процедуру с бубуном

несправедливость же - для всех остальных составных литералов бубен остался

jtootf ** (27.10.2009 16:03:41)
[#]  
jtootf (фотография)

[C++] почему?

ко второму вопросу

void g(const char a[3]) 
{ 
    std::cout << "sizeof a = " << sizeof(a) << "\n"; 
    std::cout << "strlen(a) = " << strlen(a) << std::endl; 
} 
 
... 
 
g("123456");

sizeof a = 4 
strlen(a) = 6

и у нас как бы функция типа void (const char[3]), которая на самом деле получает ни разу не const char[3]. -Wall -pedantic, ни одного предупреждения

jtootf ** (27.10.2009 16:10:04)
[#] Ответ на: [C++] почему? от LamerOk 27.10.2009 15:54:36  

Re: [C++] почему?

>И, сделав это исключение, всё таки напоролись на грабли с const, приведенные выше.

какие грабли из-за строковых литералов тебе померещились?

>С того, что этот синтаксис ортогонален синтаксису любых других константных литералов во время компиляиции

это что-то не бред больше похоже.

anonymous (27.10.2009 16:11:53)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 16:10:04  

Re: [C++] почему?

> и у нас как бы функция типа void (const char[3]), которая на самом деле получает ни разу не const char[3].

Может ты наконец поймешь разницу между указателем и массивом?

LamerOk ** (27.10.2009 16:16:38)
[#]  

[C++] почему?

> void f(const int[3]);

void f(int[const 3]);

в С99 такая запись.

dilmah ***** (27.10.2009 16:17:58)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 16:10:04  

Re: [C++] почему?

>и у нас как бы функция типа void (const char[3]), которая на самом деле получает ни разу не const char[3]. -Wall -pedantic, ни одного предупреждения

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

anonymous (27.10.2009 16:18:00)
[#] Ответ на: Re: [C++] почему? от anonymous 27.10.2009 16:11:53  

Re: [C++] почему?

> какие грабли из-за строковых литералов тебе померещились?

Тебе не понятна разница междуо объявлениями
char *t;
и
const char *t;

?

> это что-то не бред больше похоже.


Хороший способ сказать "я не понял ответа" )))

LamerOk ** (27.10.2009 16:18:25)
[#] Ответ на: Re: [C++] почему? от LamerOk 27.10.2009 16:16:38  
jtootf (фотография)

[C++] почему?

>Может ты наконец поймешь разницу между указателем и массивом?

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

jtootf ** (27.10.2009 16:21:00)
[#] Ответ на: Re: [C++] почему? от anonymous 27.10.2009 16:18:00  
jtootf (фотография)

[C++] почему?

>и что тебе удивило? что есть размер указателя?

отсутствие предупреждений во время компиляции. преобразование константного массива к указателю - не проблема, а вот обратное (с заменой размерности) уже, мягко говоря, чревато проблемами

jtootf ** (27.10.2009 16:22:34)
[#] Ответ на: Re: [C++] почему? от LamerOk 27.10.2009 16:18:25  

Re: [C++] почему?

>Тебе не понятна разница междуо объявлениями

Строковые литералы являются константами.

anonymous (27.10.2009 16:25:14)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 16:21:00  

[C++] почему?

Блджад, не тупи. Тип char[] идентичен типу char* Это разная запись одной и той же семантической конструкции.

LamerOk ** (27.10.2009 16:28:18)
[#] Ответ на: Re: [C++] почему? от anonymous 27.10.2009 16:25:14  

[C++] почему?

С какого года? Грабли, о которых я говорил, - необходимость менять тип указателя, котороый можно инициализировать стринговой литерной константой.

LamerOk ** (27.10.2009 16:30:15)
[#] Ответ на: [C++] почему? от LamerOk 27.10.2009 16:28:18  

[C++] почему?

> Тип char[] идентичен типу char*

Ламер ты и есть. Злокачественный.

tailgunner **** (27.10.2009 16:34:25)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 16:10:04  
golodranez (фотография)

Re: [C++] почему?

>void g(const char a[3])

>и у нас как бы функция типа void (const char[3]), которая на самом деле получает ни разу не const char[3].

ты не можешь передать в функцию массив. http://www.cplusplus.com/doc/tutorial/pointers/.

golodranez *** (27.10.2009 16:35:40)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 16:22:34  
Absurd (фотография)

[C++] почему?

>преобразование константного массива к указателю - не проблема, а вот обратное (с заменой размерности) уже, мягко говоря, чревато проблемами

we’re still screwing around with ’70s debuggers and linkers, and it’s stupid. I don’t know why we put up with it. (C) Brendan Eich

Absurd ** (27.10.2009 16:35:41)
[#] Ответ на: [C++] почему? от LamerOk 27.10.2009 16:30:15  

Re: [C++] почему?

>Грабли, о которых я говорил, - необходимость менять тип указателя, котороый можно инициализировать стринговой литерной константой.

что-то вроде того, что строковым литералом нужно инициализировать указатель на константу? это не грабли, так и должно быть.

anonymous (27.10.2009 16:40:47)
[#] Ответ на: [C++] почему? от LamerOk 27.10.2009 16:28:18  
Absurd (фотография)

[C++] почему?

>Тип char[] идентичен типу char* Это разная запись одной и той же семантической конструкции.

Нифига- char[] - массив, char* - указатель. Ничего общего, разве что а) У параметров функций - массивов срезается первая размерность и замещается указателем и б) при передаче массива в функцию делается автокаст массив->указатель.

Absurd ** (27.10.2009 16:41:24)
[#] Ответ на: [C++] почему? от LamerOk 27.10.2009 16:28:18  

Re: [C++] почему?

> Тип char[] идентичен типу char*

рукалицо.жпг

ntp (27.10.2009 16:41:38)
[#] Ответ на: [C++] почему? от LamerOk 27.10.2009 16:28:18  
golodranez (фотография)

[C++] почему?

не совсем - http://c-faq.com/decl/strlitinit.html

golodranez *** (27.10.2009 16:44:20)
[#] Ответ на: [C++] почему? от Absurd 27.10.2009 16:41:24  

Re: [C++] почему?

> Нифига- char[] - массив, char* - указатель. Ничего общего, разве что
... б) при передаче массива в функцию делается автокаст массив->указатель.

Это и имеется в виду. А не то, о чём вы все подумали, грязные извращенцы.

LamerOk ** (27.10.2009 16:46:51)
[#] Ответ на: Re: [C++] почему? от anonymous 27.10.2009 16:40:47  

Re: [C++] почему?

> что-то вроде того,

Что то вроде того, что синтаксис языка _ПРИШЛОСЬ МЕНЯТЬ_, блджад.

LamerOk ** (27.10.2009 16:47:25)
[#] Ответ на: Re: [C++] почему? от golodranez 27.10.2009 16:35:40  
jtootf (фотография)

[C++] почему?

Цитата

ты не можешь передать в функцию массив

template <typename T, size_t n> 
size_t size(T (&)[n]) 
{ 
   return n; 
}

у меня этот пример скоро уже в печёнках будет

jtootf ** (27.10.2009 17:40:11)
[#] Ответ на: [C++] почему? от LamerOk 27.10.2009 16:28:18  
jtootf (фотография)

[C++] почему?

Цитата

Тип char[] идентичен типу char* Это разная запись одной и той же семантической конструкции.

все милостиво над тобой поулыбались

теперь к сути вопроса:

void f(const int a[3]) 
{ 
   std::cout << "f. sizeof a = " << sizeof(a) << std::endl; 
} 
 
void g() 
{ 
   const int a[3] = {1, 2, 3}; 
 
   std::cout << "g. sizeof a = " << sizeof(a) << std::endl; 
 
   f(a); 
} 

результат где-то такой:

g. sizeof a = 12 
f. sizeof a = 4

в функции g есть локальная переменная типа int[3], в функции f есть локальная переменная типа int[3]. тип одинаковый, результат выполнения sizeof - разный. преобразование было произведено подкапотно, без лексически наблюдаемого описания, без предупреждения

jtootf ** (27.10.2009 17:44:13)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 17:44:13  

Re: [C++] почему?

> все милостиво над тобой поулыбались

Все, кроме тебя, вспомнили про разницу между типом переменной и типом выражения. А вот ты, судя по

> в функции g есть локальная переменная типа int[3], в функции f есть локальная переменная типа int[3].


её так и не понял.

LamerOk ** (27.10.2009 17:57:17)
[#] Ответ на: Re: [C++] почему? от LamerOk 27.10.2009 17:57:17  
jtootf (фотография)

[C++] почему?

>разницу между типом переменной и типом выражения

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

jtootf ** (27.10.2009 18:03:04)
[#] Ответ на: [C++] почему? от Absurd 27.10.2009 16:35:41  
jtootf (фотография)

[C++] почему?

template<size_t size> 
void ft(const int (&)[size]); 
 
template<> 
void ft(const int (&)[3]) 
{ 
   std::cout << "ft. sizeof a = 3, fixed" << std::endl; 
}

такой вариант работает, но падает совсем не так хорошо, как хотелось бы

jtootf ** (27.10.2009 18:04:45)
[#] Ответ на: Re: [C++] почему? от LamerOk 27.10.2009 17:57:17  

[C++] почему?

блин, я не разу не "сиплюсплюсник", но блин до боли в глазах и гула в голове не могу понять: где в примере переменная, а где выражение?

yyk *** (27.10.2009 18:05:39)
[#] Ответ на: [C++] почему? от yyk 27.10.2009 18:05:39  

Re: [C++] почему?

Чего ж тут непонятного? Ты видишь здесь объявление массива?

 
void f(const int a[3]) 
{ 
   std::cout << "f. sizeof a = " << sizeof(a) << std::endl; 
} 

LamerOk ** (27.10.2009 18:37:12)
[#] Ответ на: Re: [C++] почему? от LamerOk 27.10.2009 18:37:12  
Love5an (фотография)

[C++] почему?

const int a[3]

Локальная переменная-массив.

Love5an (27.10.2009 18:39:01)
[#] Ответ на: Re: [C++] почему? от LamerOk 27.10.2009 18:37:12  
jtootf (фотография)

[C++] почему?

>Ты видишь здесь объявление массива?

const int a[3]. локальная переменная функции f, имеет имя a и тип int[3]

jtootf ** (27.10.2009 18:39:25)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 17:44:13  

Re: [C++] почему?

>в функции f есть локальная переменная типа int[3]. тип одинаковый, результат выполнения sizeof - разный.

гы-гы. а ничего, что sizeof в рантайме, где уже в сях нету никаких типов.

anonymous (27.10.2009 18:50:04)
[#] Ответ на: Re: [C++] почему? от anonymous 27.10.2009 18:50:04  
jtootf (фотография)

[C++] почему?

Цитата

а ничего, что sizeof в рантайме

тебя ждёт много удивительных открытий. sizeof - compile-time операция

template <size_t n> 
int test() 
{ 
   return n; 
} 
 
... 
 
test<sizeof(char)>();

компилируется и работает на ура

jtootf ** (27.10.2009 18:57:25)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 17:40:11  
golodranez (фотография)

[C++] почему?

>template <typename T, size_t n>
size_t size(T (&)[n])
{
return n;
}

И что? Ты не передашь массив в функцию. Ты как вообще догадался объявлять функцию как f(some_type[amount]) ?

golodranez *** (27.10.2009 18:58:47)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 18:57:25  

Re: [C++] почему?

>sizeof - compile-time операция

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

anonymous (27.10.2009 19:05:21)
[#] Ответ на: [C++] почему? от golodranez 27.10.2009 18:58:47  
jtootf (фотография)

[C++] почему?

Цитата

И что? Ты не передашь массив в функцию.

*икнул* а что же я делаю?

template <typename T, size_t n> 
void print(T (&a)[n]) 
{ 
   for(int i = 0; i < n; ++i) 
   { 
      std::cout << "a[" << i << "] = " << a[i] << std::endl; 
   } 
}

вроде передаётся

Цитата

Ты как вообще догадался объявлять функцию как f(some_type[amount]) ?

потребовалось для подсчёта количества элементов сишного массива. sizeof(arr)/sizeof(elem) в таком случае не работает - благодаря всё тому же неявному преобразованию к типу указателя

jtootf ** (27.10.2009 19:08:14)
[#] Ответ на: Re: [C++] почему? от anonymous 27.10.2009 19:05:21  
jtootf (фотография)

[C++] почему?

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

это что за поток сознания? не распарсил

jtootf ** (27.10.2009 19:09:25)
[#] Ответ на: [C++] почему? от Absurd 27.10.2009 16:35:41  
jtootf (фотография)

[C++] почему?

template <bool> struct STATIC_ASSERTION_FAILURE; 
template <> struct STATIC_ASSERTION_FAILURE<true> {}; 
 
template<size_t size> 
void ft(const int (&)[size]) 
{ 
   STATIC_ASSERTION_FAILURE<false>(); 
} 
 
template<> 
void ft(const int (&)[3]) 
{ 
   std::cout << "ft. sizeof a = 3, fixed" << std::endl; 
}

а вот такой вариант, наконец-то, падает в компайл-тайм. и даже сообщение об ошибке можно прикрутить более-менее вменяемое

jtootf ** (27.10.2009 19:15:43)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 18:39:25  

Re: [C++] почему?

> const int a[3]. локальная переменная функции f, имеет имя a и тип int[3]

Ты не увиливай, а отвечай на прямо поставленный вопрос - здесь есть объявление массива или нет?

LamerOk ** (27.10.2009 19:19:29)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 19:09:25  

Re: [C++] почему?

>это что за поток сознания?

так и запишем: автор не осилил, но осуждает.

anonymous (27.10.2009 19:22:33)
[#] Ответ на: [C++] почему? от jtootf 27.10.2009 19:15:43  
Absurd (фотография)

Re: [C++] почему?

>а вот такой вариант, наконец-то, падает в компайл-тайм.

Это фейл. Функция ft должна быть в .c++ файле и оно должно падать в линк-тайм.

Absurd ** (27.10.2009 19:24:58)
[#] Ответ на: Re: [C++] почему? от LamerOk 27.10.2009 19:19:29  
jtootf (фотография)

[C++] почему?

для человека, сказавшего правильно и по существу на весь тред всего пару фраз, ты удивительно надоедлив. да, здесь есть объявление массива

jtootf ** (27.10.2009 19:25:02)
[#] Ответ на: Re: [C++] почему? от Absurd 27.10.2009 19:24:58  
jtootf (фотография)

[C++] почему?

>Это фейл

почему?

>Функция ft должна быть в .c++ файле и оно должно падать в линк-тайм.

предыдущий вариант падает в линк-тайм. этот - в компайл-тайм. сообщение об ошибке здесь куда более читаемое, чем там

jtootf ** (27.10.2009 19:26:16)

http://www.linux.org.ru/

Rambler's Top100 TopList