Членское расположение C++

Позвольте нам, у нас есть простая структура (POD).

struct xyz
{
    float x, y, z;
};

Я могу предположить, что следование коду в порядке? Я могу предположить, что нет никаких разрывов? Что говорит стандарт? Действительно ли это верно для ПЕРЕХОДНЫХ ПРИСТАВОК? Действительно ли это верно для классов?

xyz v;
float* p = &v.x;
p[0] = 1.0f;
p[1] = 2.0f; // Is it ok?
p[2] = 3.0f; // Is it ok?
6
задан Sergey K. 16 July 2012 в 08:36
поделиться

9 ответов

Ответ здесь немного сложно. Стандарт C ++ говорит, что типы данных POD будут иметь CARNAME CARNAME CARNAME CARNAL ( ). Согласно разделу 9.2 9.2 Спекунта C членов структуры будут выложены в последовательном порядке, если

  1. нет разности модификатора доступности
  2. Нет проблем выравнивания с типом данных

так Да, это решение будет работать до тех пор, пока тип поплавок имеет совместимое выравнивание на текущей платформе (это размер слов платформы). Таким образом, это должно работать на 32-битные процессоры, но я предполагаю, что он не удастся за 64 бит. По сути, в любом месте, что SizeOf (void *) отличается от SizeOf (float)

10
ответ дан 8 December 2019 в 04:29
поделиться

Я бы на самом деле написал свою небольшую функцию, которая делает трюк, используя простой старый доступ char:

public static String trimBackslash( String str )
{
    int len, left, right;
    return str == null || ( len = str.length() ) == 0 
                           || ( ( left = str.charAt( 0 ) == '\\' ? 1 : 0 ) |
           ( right = len > left && str.charAt( len - 1 ) == '\\' ? 1 : 0 ) ) == 0
        ? str : str.substring( left, len - right );
}

Это ведет себя так же, как String.trim (), только то, что он работает с '\' вместо космоса.

Вот одна альтернатива, которая работает и фактически использует обрезку ();) Хотя это не очень эффективно, это, вероятно, обыграет все подходы на основе regexp исполнения мудро.

String j = “\joe\jill\”;
j = j.replace( '\\', '\f' ).trim().replace( '\f', '\\' );
-121--994928-

Маршрутизация

MapQuest open предлагает сервис Open Directions и Open Guidance Service .

Дополнительную информацию о маршрутизации в OpenStreetMap можно найти в статье Маршрутизация на вики-сайте OSM .

Геокодирование

Cloudmade API веб-карт включает геокодер. В настоящее время на основном сайте OpenStreetMap используются Nominatim и GeoNames . Существует также служба открытого геокодирования MapQuest .

-121--1393395-

Как отмечали другие, выравнивание не гарантируется спецификацией. Многие говорят, что оно зависит от оборудования, но на самом деле оно также зависит от компилятора. Аппаратное обеспечение может поддерживать различные форматы. Помню, что компилятор PPC поддерживает прагматики, как «упаковать» данные. Вы можете упаковать его на «родные» границы или принудить его к 32-битным границам и т.д.

Было бы неплохо понять, что вы пытаетесь сделать. Если вы пытаетесь «разобрать» входные данные, вам лучше использовать реальный синтаксический анализатор. Если вы собираетесь сериализовать, то напишите настоящий сериализатор. Если вы пытаетесь сдвинуть биты, например, для драйвера, то спецификация устройства должна дать вам конкретную карту памяти для записи. Затем можно записать структуру POD, указать правильные прагматики выравнивания (если поддерживаются) и двигаться дальше.

0
ответ дан 8 December 2019 в 04:29
поделиться

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

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

p[1]

даст вам мусор, а

p[2]

- то, что вы думаете, вы получите от

p[1]

&c.

Однако, ваш компилятор может дать вам некоторую возможность упаковать структуру. Это все равно не было бы "стандартом" - стандарт не предусматривает ничего подобного, и разные компиляторы предоставляют очень несовместимые способы сделать это - но, скорее всего, он будет более переносимым.

1
ответ дан 8 December 2019 в 04:29
поделиться

Ответ здесь немного хитрый. В стандарте C++ указывается, что типы данных POD будут иметь гарантии совместимости формата C ( Ссылка ). В соответствии с разделом 9,2 спецификации C членов структуры будет располагаться в последовательном порядке, если

  1. нет разницы модификаторов доступности
  2. Нет проблем выравнивания с типом данных

Поэтому да, это решение будет работать, пока тип float имеет совместимое выравнивание на текущей платформе (это размер слова платформы). Так что это должно работать для 32-разрядных процессоров, но я предполагаю, что это не сработает для 64-разрядных. По существу, где размер (пустота *) отличается от размера (поплавок)

-121--4116867-

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

С другой стороны, использование J хорошо, если вы хотите: разбор, просеивание, анализ, критический анализ и т.д. некоторые данные, которые необходимо обработать, чтобы выяснить тонкое зерно алгоритма, или впечатлить интернеты кратчайшим возможным способом вычислить, сколько треугольников вписывается в круг или что нет.

Я подошел очень близко к добавлению J в качестве нарушителя сделки в профиль моей карьеры на careers.stackoverflow.com , но я в конечном итоге оставил это. Для меня использование J хорошо, производство J, однако, не является.

EDIT:

Это было некоторое время назад. Я до сих пор плохо думаю о полных J-решениях в производстве (то есть о всех ваших MVC). С момента первоначального ответа я использовал J в качестве COM в проекте C #, где J предоставляется с большой матрицей, которой с большим удовлетворением можно управлять в C #.

Часть нашей работы заключается в том, чтобы модели данных и код говорили . Это не просто соединить это качество и J очень терпкий синтаксис. Несколько рамки, в отличие от J, имеют простоту в работе с IDE и имеют достаточную поддержку, позволяющую упорядочивать код в удобочитаемом для человека пути. Возможности матрицы J не компенсируют то, чего ей не хватает.

-121--1122643-

Ваш код - OK (при условии, что он обрабатывает только данные, сгенерированные в той же среде). Структура будет размещена в памяти как объявленная, если она является POD. Однако в целом существует готча, о которой нужно знать: компилятор будет вставлять в структуру набивку, чтобы гарантировать соблюдение требований каждого члена к выравниванию.

Если бы ваш пример был

struct xyz
{
    float x;
    bool y;
    float z;
};

, то z начал бы 8 байт в структуре и размер (xyz) был бы 12, как float s (обычно) 4 байт выровнены.

Аналогично, в случае

struct xyz
{
    float x;
    bool y;
};

sizeof (xyz) = = 8, чтобы обеспечить ((xyz *) ptr) + 1 возврат указателя, который соответствует требованиям выравнивания x.

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

0
ответ дан 8 December 2019 в 04:29
поделиться

В случае сомнений, измените структуру данных в соответствии с приложением:

struct xyz
{
    float  p[3];
};  

Для чтения для чтения вы можете рассмотреть вопрос:

struct xyz
{
    enum { x_index = 0, y_index, z_index, MAX_FLOATS};
    float p[MAX_FLOATS];

    float  X(void) const {return p[x_index];}
    float  X(const float& new_x) {p[x_index] = new_x;}

    float  Y(void) const {return p[y_index];}
    float  Y(const float& new_y) {p[y_index] = new_y;}

    float  Z(void) const {return p[z_index];}
    float  Z(const float& new_z) {p[z_index] = new_z;}
};

Возможно, даже добавить еще немного инкапсуляции:

struct Functor
{
  virtual void operator()(const float& f) = 0;
};

struct xyz
{
  void for_each(Functor& ftor)
  {
     ftor(p[0]);
     ftor(p[1]);
     ftor(p[2]);
     return;
  }
  private:
     float p[3];
}

в целом, Если структура данных должна рассматриваться в двух или более разных способах, возможно, структура данных должна быть переработана; или код.

2
ответ дан 8 December 2019 в 04:29
поделиться

Зависит от аппаратного обеспечения. Стандарт явным образом позволяет классам POD иметь неопределенную и непредсказуемую подкладку. Я заметил это на странице Википедии на C++ и взял сноску со спецификацией для вас.

^ a b ISO/IEC (2003). ISO/IEC 14882:2003(E): Языки программирования - C++ §9.2 Члены класса [class.mem] параграф. 17

Однако на практике на обычных аппаратных средствах и компиляторах все будет хорошо.

2
ответ дан 8 December 2019 в 04:29
поделиться

Просто добавьте файл show.json.erb с содержимым

<%= @user.to_json %>

Иногда это полезно, когда вам нужны дополнительные вспомогательные методы, которые недоступны в контроллере, т.е. image _ path (@ user.avatar) или что-то еще для создания дополнительных свойств в JSON:

<%= @user.attributes.merge(:avatar => image_path(@user.avatar)).to_json %>
-121--3476885-

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

-121--2590287-

Нет, это не нормально, за исключением первого поля.

Из стандартов C++:

9,2 Члены класса
Указатель на объект структуры POD, соответствующим образом преобразованы с использованием reinterpret_cast, указывает на его начальный член (или если этот член является bit-field, затем в блок, в котором он проживает) и наоборот. Примечание: Поэтому может быть и неназванное заполнение в объекте структуры POD, но не в начале, по мере необходимости для достижения соответствующего согласования.

4
ответ дан 8 December 2019 в 04:29
поделиться

Нет, это не нормально, за исключением первого поля.

Из стандартов C++:

9,2 Члены класса
Указатель на объект структуры POD, соответствующим образом преобразованы с использованием reinterpret_cast, указывает на его начальный член (или если этот член является bit-field, затем в блок, в котором он проживает) и наоборот. Примечание: Поэтому может быть и неназванное заполнение в объекте структуры POD, но не в начале, по мере необходимости для достижения соответствующего согласования.

-121--4116876-

Зависит от аппаратных средств. Стандарт явно позволяет классам POD иметь неопределенную и непредсказуемую набивку. Я отметил это на странице Википедии C++ и схватил сноску со ссылкой на спецификацию для вас.

a b ISO/IEC (2003). ISO/IEC 14882:2003 (E): Programming Languages - C++ § 9,2 Члены класса [class.mem] параграф 17

На практике, однако, на общем оборудовании и компиляторах это будет хорошо.

-121--4116875-

Это не гарантируется стандартом и не будет работать во многих системах. Причины:

  • Компилятор может выравнивать членов структуры в соответствии с целевой платформой, что может означать 32-разрядное выравнивание, 64-разрядное выравнивание или что-либо еще.
  • Размер плавающего элемента может составлять 32 бит или 64 бит. Нет гарантии, что она совпадает с выравниванием члена структуры.

Это означает, что p [1] может находиться в том же месте, что и xyz.y , или может частично перекрываться или вообще отсутствовать.

5
ответ дан 8 December 2019 в 04:29
поделиться

Стандарт требует, чтобы порядок расположения в памяти соответствовал порядку определения, но допускает произвольную подкладку между ними. Если у вас есть спецификатор доступа (public:, private: или protected:) между членами, даже гарантия на порядок теряется.

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

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

1
ответ дан 8 December 2019 в 04:29
поделиться