LINUX.ORG.RU

Как передать число по в функцию?


0

0

есть, скажем, функция:
 void myarr_push(myarr** arr, void* val);

val можно передать следущим образом:
 int q = 10;
 myarr_push(..., (void *)&q);

А как передать просто число не заводя для этого переменную? Т.е хочется что-то вроде этого:
 myarr_push(..., &5); // смотрится немного абсурдно, но смысл понятен

Реально ли так сделать, или нет? Спасибо.


P.S. "void* val" заведомо меняться не будет в функции.
anonymous

>Реально ли так сделать, или нет?

нет

anonymous
()

>"void* val" заведомо меняться не будет в функции.

А зачем тогда указатель, если значение меняться не будет??

ProtecT
()

по вопросу: нет низзя!
>P.S. "void* val" заведомо меняться не будет в функции.
тогда, добавь const

phrm ★★
()
Ответ на: комментарий от ProtecT

> А зачем тогда указатель, если значение меняться не будет??
затем, что бы с произвольным типом работать :).

anonymous
()
Ответ на: комментарий от phrm

> тогда, добавь const

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

anonymous
()
Ответ на: комментарий от anonymous

а может тебе функцию описать так ?
void myarr_push(myarr** arr, ...);
или у тебя в структуре указатели храняться ?

anonymous
()

Если хочешь работать с любыми типами, то используй шаблоны. А если тебе сам адрес не нужен, то и передавай значение.

devinull ★★
()
Ответ на: комментарий от anonymous

Сам подумай, если ты хочешь передавать адрес, то нужно предварительно создать переменную (иначе как можно передать адрес того чего нет?), а если тебе нужно только значение, используй обычный #define

shumer
()

Можно просто так:

myarr_push(..., (void *) 5);

Все равно тебе надо будет как-то догадаться о том, что за 
реальный тип был у параметра. Почему бы не думать просто о 
"целое приведенное к указателю на void" как об еще одном типе?:

myarr_push(myarr** arr, void* val)
{
   . . .
   if(тип был int){
      int i=(int)val;
      . . .
   }
   . . .
}

Целое всегда влезет в указатель, а знаковое расширение все правильно сделает на 64 системе.

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

Die-Hard ★★★★★
()

Если это С++, то перегрузка функций самое оно в таком случае. То есть:

void myarr_push (myarr** arr, int val);
void myarr_push (myarr** arr, char* val);
void myarr_push (myarr** arr, float val);
и т.д.


Shmuma
()
Ответ на: комментарий от Shmuma

Shmuma (28.04.2006 10:30:35):

> ...перегрузка функций самое оно...

Это -- самое _не_ оно!

1. Человек хочет сэкономить _одну_ячейку_, а ты предлагаешь кучу функций!

2 Это _вообще_ не то, поскольку тип параметра при вызове перегруженной функции дожен быть известен во время компиляции. На ЦеПП то, что требуется в вопросе, соответствует передаче в качестве параметра полиморфика.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

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

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

Shmuma
()
Ответ на: комментарий от Shmuma

Shmuma (28.04.2006 21:54:38):

> 1. Экономия на спичках в данном случае вредна, имхо.

Эта экономия, однако, присутствует в условии задачи.

> ... более понятным кодом, ...

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

> 2. да, но зачем нужен полностью произвольный тип элемента массива, ...

Массив тут не при чем.

> ... не известный на этапе компиляции?

Есть такая штука, полиморфизм называется :)

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Эта экономия, однако, присутствует в условии задачи.

изначально хотели избавиться от лишней локальной переменной. Ее и не будет: myarr_push (..., 5);

> Есть такая штука, полиморфизм называется :)

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

> За ней нет ничего, кроме мнемоники, делегированной компилятору.

Ты точно уверен насчет _мнемоники_? http://www.wikiznanie.ru/ru-wz/index.php/Мнемоника

А насчет запутанности кода... Ты действительно уверен что (void*) сильно лучше будет? Напишешь switch на 10 экранов, и что дальше? Но самое непрятное даже не в этом. Если потом нужно будет добавить еще один тип, а switch поправить ты забудешь, компилятор тебе даже не пикнет про это. В случае с перегрузкой функций будет ошибка компиляции именно на вызове с аргументом непредусмотренного типа.

> Массив тут не при чем.

Как быть с именем функции: myarr_push? Только для примера?

Ладно, пофиг, я свое решение не навязываю -- это все сплошное имхо. Если все-таки про массив объектов разного типа, то код будет примерно такой:

<pre> enum item_type_t { IntItem, FloatItem, StringItem, };

typedef union { int int_i; float float_i; char* string_i; } arr_data_t;

typedef struct { item_type_t t; arr_data_t d; } arr_t;

void myarr_push (arr_t* arr, int val) { // create new arr item and other stuff arr.t = IntItem; arr.d = val; } </pre>

Для остальных нужных типов аналогично.

Shmuma
()
Ответ на: комментарий от Shmuma

Блин, и когда на лоре будет предварительный просмотр?

enum item_type_t {
  IntItem,
  FloatItem,
  StringItem,
};

typedef union {
  int int_i;
  float float_i;
  char* string_i;
} arr_data_t;

typedef struct {
  item_type_t t;
  arr_data_t d;
} arr_t;

void myarr_push (arr_t* arr, int val)
{
  // create new arr item and other stuff
  arr.t = IntItem;
  arr.d = val;
}

Shmuma
()
Ответ на: комментарий от Shmuma

Shmuma (*) (29.04.2006 0:05:57):

> изначально хотели избавиться от лишней локальной переменной. Ее и не будет: myarr_push (..., 5);

Угу, только вместо 4-х байтной ячейки будет много_кило_байтный код несколких функций.

>> Есть такая штука, полиморфизм называется :)

> верно, есть. Только он здесь совсем ни при чем: 1. про классы речь не шла

Полиморфизм реализуем безо всяких классов. И даже вне ООП парадигмы.

> 2. информация о типе при использовании полиморфизма все-таки присутствует -- тип базового класса.

Это -- артефакт ООП. В общем случае семантику и данные можно разделять (по научному это называется "нарушением инкапсуляции" :-)). Следуя моде, иногда народ от этого пищит и прется (например, отделение интерфейса от имплементации), а иногда сурово осуждает (например, Пыхпых).

Вообще, передача void * на Це -- стандартный способ осуществления позднего связывания -- того, что в ООП называется полиморфизмом. Перегрузка же функций к ООП не имеет отношения вообще (и к позднему связыванию, в частности) и является чисто мнемоническим приемом.

>> За ней нет ничего, кроме мнемоники, делегированной компилятору.

>Ты точно уверен насчет _мнемоники_? http://www.wikiznanie.ru/ru-wz/index.php/Мнемоника

Да.

Ты приводишь ссылку на толкование термина психологией, а в рамках информатики это трактуется чуть иначе, как правила (любые) создания идентификаторов.

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

> Ты действительно уверен что (void*) сильно лучше будет?

1. Еще раз -- это _совершенно_ другое. (void*) обычно передается для _позднего_ связывания, где перегрузка функций _никак_ не может помочь. В моем примере это было просто описание концепции.

2. Вообще говоря, я считаю что свитч на 10 экранов лучше полусотни перегруженных функций. Я отдаю себе отчет в том, что большинство присутствующих со мной не согласятся -- последнее я обьясняю массовой промывкой мозгов (ИМХО вредными) концепциями ООП в трактовке ЦеПП.

Die-Hard ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.