Указатель на член - элемент массива

Dmitriy82


struct S{
int arr[8];
}

...
int S::*ptr;
ptr=&S::arr[0];
...

Ругается на последнюю строчку subscript requires array or pointer type.
Возможно ли, и если да то как правильно записать то, что я имел ввиду (указатель на первый элемент массива)?

sbs-66

Ты б хоть язык указал.

vall

это что за аццкий с++ !?

Elina74

До тех пор пока ты не ввел ни одной переменной типа S ты не можешь обращаться к ее(?) внутренностям. Это же самые начала ООП.

margadon

а чего ты хочешь добиться этим кодом?

Dmitriy82

Получить указатель на член, который указывал бы на первый элемент массива этой структуры. Чтобы с его помощью в дальнейшем можно было для любого экземпляра этой структуры обращаться к первому элементу массива (S s; s.*ptr=17; )

vall

мехмат?

Ober

Так что за язык-то? Только не говори, что это C, или, что C++, после таких фрагментов кода в это поверить очень сложно

bobby

Если использовать то, что смещение начала массива в структуре совпадает (по значению, но не по типу) со смещением первого элемента массива, можно написать:
struct S {
int arr[8];
}

...
int S::* ptr = reinterpret_cast<int S::*>(&S::arr);
S s;
s.*ptr = 15;
std::cout << s.arr[0] << std::endl; // Выведет 15
...
Но вообще-то это жесть

Codcod

struct S{
int arr[8];
}

...
int S::*ptr;
ptr=&S::arr[0];
...
что это за нах?
Пиши русским языком!
struct S
{
int arr[8];
};
...
S test;
int *ptr;
ptr=&test.arr[0];
...

bobby

Нужно было несколько другое.

yolki

а что нужно было-то?

bobby

Чтобы [..] в дальнейшем можно было для любого экземпляра этой структуры обращаться к первому элементу массива (S s; s.*ptr=17;)
S s1, s2;
s1.*ptr = 10; // == s1.arr[0]
s2.*ptr = 12; // == s2.arr[0]
И т.п.

tokuchu

ptr=&test.arr[0];
Да ну вы все извращенцы.
В C имя массива само по себе является указателем на его первый элемент.

Missi4ka

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

bobby

Ты, другими словами, хочешь создать алиас для элемента массива, где массив — это поле структуры.
Начнём с того, что хочу не я.
Но такого нельзя сделать даже для самого поля, не говоря уж об энном элементе массива.
Для самого поля это сделать можно в С++ (получить и сохранить смещение поля внутри структуры). Попробуй скомпилировать код, который я привел, и разобраться в нём.

erotic

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

margadon

при всём при этом код вполне себе работает

Missi4ka

Начнём с того, что хочу не я.
извини, не туда пост приклеил.
Честно говоря, уже не помню, является ли допустимой по стандарту операция
p = S::*f; 
где f — поле структуры, или нужно делать через экземпляр. Но в любом случае, можно взять поинтер на сам массив, считая, что это и есть его нулевой элемент. Дальше — смещение на размер элемента (грязновато, конечно).

margadon

p = S::*f;
вряд ли
но в вышеупомянутом коде такой операции нет

mira-bella

а пробовал вот так:

struct S{
int arr[8];
}

...
int S::*ptr;
ptr = S::arr;
...

?

mira-bella

reinterpret_cast<int S::*>
как известно код с reinterpret_cast является заведомо не портируемым (корректным синтаксически, но некорректным функционально)

margadon

а это не будет работать - arr не static

mira-bella

а это не будет работать - arr не static
и что?
Где в коде намек на то, что он должен быть static?

amkharchenko

По мнению многих сексопатологов указателем на член является мужской галстук.

margadon

что-что
не скомпилируется

mira-bella

на gcc-4.1.1 не работает
все это очень хорошо иллюстрирует, что C++ - говно.
PS: Не стОит использовать тупые фичи (типа указателей на нестатические члены класса если сами авторы языка их еще до конца не продумали или авторы самых распространенных компиляторов не реализовали. Не надо добавлять на свою голову проблем.

mira-bella

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

Dasar

фигней страдаете.
раз в коде явно(статически) указан размер массива значит его надо и дальше везде указывать явно
int * arr и int arr[8] - это разные типы

struct S{
int arr[8];
int q;
};

typedef int (IntArray8)[8];

int main(array<System::String ^> ^args)
{
IntArray8 S::*ptr = &S::arr;

S obj;
obj.arr[0] = 5;

std::cout << (obj.*ptr)[0] << std::endl;

return 0;
}

Dmitriy82

>int * arr и int arr[8] - это разные типы
Но элемент-то массива - это int в любом случае. А нужно мне это вот для чего. В реальной задаче массив многомерные, а мне надо пройтись по набору таких структур и произвести операцию над определенными (везде одними и теми же) элементами массива. Хотелось бы сделать это наиболее красиво и эффективно. Обращение по нескольким индексам естественно медленнее, чем разыменовывание указателя на член, но я не смог записать получение указателя на член, являющийся элементом массива, и поинтересовался, возможно ли это вообще (здравый смысл подсказывает, что возможно, так же как указатель на int может указывать на элемент массива интов). И столкнулся с непониманием. reinterpret_cast и тому подобное нежелательны, т.к. концепция указателя на член, как я понимаю, и выступает альтернативой херне типа
#define OFFSET(STRUCT,FIELD) int &*(STRUCT*0.FIELD )

Dasar

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

struct Point
{
int x;
int y;
};

struct S{
int arr[8];
Point p;
};


ты хочешь получить смещение для p.y относительно S.
afaik, C++ в явном виде такое записывать не умеет.

Dmitriy82

Нет, я хочу получить смещение элемента массива относительно внешней структуры. В данном случае - смещение arr[0] относительно S. Но вообще похожие ситуации. А что значит в явном виде? Как ещё?

Dasar

Как ещё?
допустим так:

S s;
int offset = (char*)&s.arr[1] - (char*)&s;

erotic

И что потом с offset делать?

erotic

ты хочешь получить смещение для p.y относительно S.
Можно так:
 	Point S::* Sptr = &S::p;
int Point::* Pptr = &Point::x;

Point p = {1, 2};
S d;
d.*Sptr.*Pptr = 10;

Dasar

писать простую и интуитивно понятную конструкцию

S ss[10];
for (int i = 0; i < 10; ++i)
*int*char*)&(ss[i] + offset = i;

Dasar

> Можно так:
но в этом коде два смещения, соответственно которые каждый раз складываются.
хочется именно одно смещение для оптимизации производительности

vall

чем тебя дейфайны с тайп кастами не устраивают?

mira-bella

(char*)
Тебя умные книжки еще не научили, что такое преобразование типа использовать в C++ крайне нежелательно (на его месте компилятор поставит static_cast, const_cast, reinterpret_cast - что первым подойдет из этой последовательности)?

mira-bella

ты пишешь не на C++, а на C для компилятора C++

poi1981

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

mira-bella

уже из содержимого моего поста ясно, почему это нежелательно (хотя эту тему можно осветить подробнее, например изложить почему дальновидные программисты не используют const_cast и reinterpret_cast)
PS: не знаю как кто, а лично я книжки по языкам программирования читаю не для того, чтобы их зубрить и пересказывать, а чтобы вникать в логику соответствующего ЯП.

poi1981

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

sbs-66

дальновидные программисты не используют const_cast
И почему же?

mira-bella

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

mira-bella

И почему же?
очевидно потому, что константный указатель может указывать на read only область памяти (стандарт и Страуструп это разрешают)

Dasar

> Тебя умные книжки еще не научили
к сожалению, C/C++ - это не тот язык, "приколы" которого хочеться помнить...

mira-bella

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

Dasar

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

alexkravchuk

(на его месте может быть поставлено static_cast, const_cast, reinterpret_cast - что первым подойдет из этой последовательности)
Слишком громоздко и из-за этого некрасиво.

mira-bella

(на его месте может быть поставлено static_cast, const_cast, reinterpret_cast - что первым подойдет из этой последовательности)
Слишком громоздко и из-за этого некрасиво.
если слишком громоздко и некрасиво, то можно не писать на C++
Я так понял требуется уточнение: цитата в скобках говорит НЕ о том, что программист может сделать (как я уже говорил const_cast, reinterpret_cast будут ставить только неумные программисты а о том, что компилятор будет делать, когда встретит C-шный синтаксис преобразования типа.
т.е. замечание в скобках следует читать так:
вместо (some_type)Val компилятор поставит static_cast<some_type>(Val const_cast<some_type>(Val reinterpret_cast<some_type>(Val) - что первым подойдет из этой последовательности
и отсюда и очевидно почему C-шный синтаксис (some_type)Val не стОит использовать, а именно из за возможности пулучить const_cast или reinterpret_cast
Оставить комментарий
Имя или ник:
Комментарий: