Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Указатели на void, тонкости реализации таких указателей 
V
    Опции темы
FiMa1
Дата 4.8.2007, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 408
Регистрация: 23.9.2006

Репутация: 5
Всего: 6



Доброго здравия, друзья!
Есть два варианта реализации функции compare - см. ниже (прошу не обращать внимания на то, что одна функция сравнения вызывает другую, баян не мой, да и не в этом суть..). Почему обе версии функции будут вполне работоспособны, какова же специфика реализации указателей на void? согласно первого варианта функции могу заключить, что указатель на void фактически есть указатель на указатель на нечто (это нечто будет определено во время выполнения программы), с другой стороны, второй вариант функции противоречит данному сделанному выводу... К сожалению, не нашел для себя ответа в стандарте, подскажите, пожалуйста.
Код
// упорядочение с помощью библиотечной функции qsort()
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;

// сравнивает значение с помощью указателей на них
int compare(const void *a, const void *b)
{
    char *pa = *(char **)a;
    char *pb = *(char **)b;
    return strcmp(pa, pb);

    /* версия 2
    unsigned long *pa = (unsigned long *)a;
    unsigned long *pb = (unsigned long *)b; 
    return strcmp((char *)*pa, (char *)*pb);*/
}

void main()
{
    char *text[] = { "Sun", "Form", "Dog", "Area", "Item" };
    const int TXTLEN = sizeof(text) / sizeof(text[0]);

    cout << "Before sorting:" << endl;
    for(int i = 0; i < TXTLEN; i++)
        cout << text[i] << ' ';
    cout << endl;

    // упорядочить текст
    qsort( (void *)text,    // адрес начала текста
           TXTLEN,          // количество слов в тексте
           sizeof(text[0]), // размер одного элемента
           compare          // имя функции сравнения (указатель)
         );
  
    cout << "After sorting:" << endl;
    for(int i = 0; i < TXTLEN; i++)
        cout << text[i] << ' ';
    cout << endl;
}

PM   Вверх
Daevaorn
Дата 4.8.2007, 16:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(FiMa1 @  4.8.2007,  17:19 Найти цитируемый пост)
Почему обе версии функции будут вполне работоспособны, какова же специфика реализации указателей на void? 

никакой специфики нет. void* это просто указаетль на нетипизированную память.
Цитата(FiMa1 @  4.8.2007,  17:19 Найти цитируемый пост)
согласно первого варианта функции могу заключить, что указатель на void фактически есть указатель на указатель на нечто (это нечто будет определено во время выполнения программы), с другой стороны, второй вариант функции противоречит данному сделанному выводу... 

что противоречит чему не понятно. как ты преобразуешь указатели не важно, важно то что изначально есть текст char*  и  в strcmp попадает тоже char*. все промежуточные преобразования не имеют значения.
PM MAIL WWW   Вверх
FiMa1
Дата 4.8.2007, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 408
Регистрация: 23.9.2006

Репутация: 5
Всего: 6



Цитата
как ты преобразуешь указатели не важно, важно то что изначально есть текст char*  и  в strcmp попадает тоже char*. все промежуточные преобразования не имеют значения.

Для меня они сейчас имеют значение, т.к. хотелось бы разобраться...
Пусть a - указатель на нетипизированную память, но я точно знаю, что по данному адресу в памяти находится переменная типа char, тогда почему я не могу написать так:
Код
char *pa = (char *)a;
char *pb = (char *)b;
return strcmp(pa, pb);

PM   Вверх
Daevaorn
Дата 4.8.2007, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(FiMa1 @  4.8.2007,  18:56 Найти цитируемый пост)
Пусть a - указатель на нетипизированную память, но я точно знаю, что по данному адресу в памяти находится переменная типа char, тогда почему я не могу написать так:

там не находится переменная типа char, там находится переменная типа char*, т.е. строка.

Это сообщение отредактировал(а) Daevaorn - 4.8.2007, 18:23
PM MAIL WWW   Вверх
Ln78
Дата 4.8.2007, 18:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 13
Всего: 15



FiMa1, а почему ты решил, что не можешь так написать? Можно написать и без использования дополнительных переменных:
Код

return strcmp((char *)a, (char *)b);

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

class CX
{
    int x;
};
class CY
{
    int y;
};
class CZ : public CX, public CY
{
    int z;
};

..................................................

    CZ z;
    CZ *pz = &z;
    CX *px = &z;
    CY *py = &z;
    CY *py2 = (CY*)(void*)&z; //Так нельзя ошибка
    CY *py3 = (CY*)(int*)&z; //Так тоже ошибка


PM MAIL   Вверх
Daevaorn
Дата 4.8.2007, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(Ln78 @  4.8.2007,  19:56 Найти цитируемый пост)
а почему ты решил, что не можешь так написать? Можно написать и без использования дополнительных переменных:

но получится не тот результат.
PM MAIL WWW   Вверх
Ln78
Дата 4.8.2007, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 13
Всего: 15



Daevaorn, я что-то не понял, почему другой? Я сейчас под отладчиком посмотрел пример:
Код

int Cmp(void* s0, void* s1)
{
    return strcmp((char*)s0, (char*)s1);
}
....................................
    char s0[]="Первое", s1[]="Второе";
    int i1 = Cmp(s0, s1);
    int i2 = strcmp(s0, s1);

Разницы не увидел: в функцию strcmp (у меня VS, смотрел файл crt\src\intel\strcmp.asm) в регистр esp передаются в обоих случаях одинаковые числа. В чём отличие?
PM MAIL   Вверх
Daevaorn
Дата 4.8.2007, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(Ln78 @  4.8.2007,  20:21 Найти цитируемый пост)
я что-то не понял, почему другой? 

у автора массив строк.
PM MAIL WWW   Вверх
Ln78
Дата 4.8.2007, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 13
Всего: 15



Да, я невнимательно посмотрел: только на функцию  compare (Я не заметил, что в первом посте код - прокручивающийся список, поэтому main совсем не видел, бывает smile )
PM MAIL   Вверх
FiMa1
Дата 4.8.2007, 19:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 408
Регистрация: 23.9.2006

Репутация: 5
Всего: 6



Цитата
там не находится переменная типа char, там находится переменная типа char*, т.е. строка.

Ага, логично, спасибо.
Цитата
Тонкости преобразований проявляются при множественном наследовании. Например, посмотри под отладчиком код...

Ммм.. ошибка, я так понимаю в получении не ожидаемого результата от преобразования ( py2 0x0012ff58 {y=5 }, py3 0x0012ff58 {y=5 } см. вариант ниже). Вряд ли разберусь почему такие результаты.. Это как-то пересекается с Апрельской темкой? Что за темка, где почитать?
Код
class CX
{
public:
    CX() { x = 5; }
private:
    int x;
};
class CY
{
public:
    CY() { y = 10; }
private:
    int y;
};
class CZ : public CX, public CY
{
public:
    CZ() { z = 15; }
private:
    int z;
};

int main()
{
    CZ z;
    CZ *pz = &z;
    CX *px = &z;
    CY *py = &z;
    CY *py2 = (CY*)(void*)&z; //Так нельзя ошибка
    CY *py3 = (CY*)(int*)&z; //Так тоже ошибка
}


Это сообщение отредактировал(а) FiMa1 - 4.8.2007, 19:47
PM   Вверх
Ln78
Дата 4.8.2007, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 13
Всего: 15



FiMa1, ну та самая тема, про массивы. Но я, из-за своей невнимательности не полностью прочитал твой этот вопрос, поэтому и неправильно его понял (Кстати, qsort - функция, которая во времена BC3.1 и Windows NT 4.0 разрушила мои представления о мощности NT, подвесив компьютер при эксперименте с неправильной подачей аргументов для неё).
По поводу множественного наследования: когда ты делаешь первые 3 преобразования 
Код

    CZ *pz = &z;
    CX *px = &z;
    CY *py = &z;

компилятор знает, с какими типами он оперирует, и адреса-числа у px и py разные. А если ты вводишь промежуточный посторонний тип (неважно какой, в примерах и void, и int), то компилятор уже такие преобразования чисел не делает, поэтому результат получается не тот, который можно ожидать
PM MAIL   Вверх
FiMa1
Дата 5.8.2007, 04:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 408
Регистрация: 23.9.2006

Репутация: 5
Всего: 6



Все понятно. Ln78, Daevaorn, спасибо вам пребольшое!
Цитата
там не находится переменная типа char, там находится переменная типа char*, т.е. строка.

Было определяющей фразой smile
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0498 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.