хранение значений в союзе в с - PullRequest
1 голос
/ 30 июня 2011

Если у нас есть объединение с тремя переменными int i, char c, float f;и мы сохраняем значение, скажем, в переменной c сейчас.и мы забываем, какая переменная объединения содержит значение в настоящее время, через некоторое время.для этого существует какой-либо механизм, предоставляемый языком, с помощью которого мы можем выяснить, является ли это i или c или f, который в настоящее время содержит значение.

Ответы [ 6 ]

3 голосов
/ 30 июня 2011
#define VARIANT_FLOAT_TYPE 1
#define VARIANT_DOUBLE_TYPE 2
// and so on

struct variant_wb {
    union {
        float f;
        double d;
        int i;
        char c;
    };
    int stored_type;
};

Тогда вы можете использовать это так:

struct variant_wb var;
var.f = 1.23;
var.stored_type = VARIANT_FLOAT_TYPE;

Вы могли бы также сделать множество функций для работы с этой структурой / объединением, или вы могли бы выучить C ++ и делать это «правильно», так как этот язык имеет функцию такого типа. Мой C ++ не очень хорош, может быть, некоторые гуру могли бы показать, как сделать подобное решение, но на C ++.

3 голосов
/ 30 июня 2011

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

3 голосов
/ 30 июня 2011

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

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

2 голосов
/ 30 июня 2011

В C ++ / Qt / COM / DCOM есть понятие «Вариант», то есть грубо говоря, объединение, которое также хранит способ обращения к объединению. В C вы должны предоставить что-то вроде этого:

struct myCVariant
{
  int variantType;
  union 
  {
    char  v1;
    int   v2;
    float v3;
  } variantContent;

  void initVariant() 
  {
    variantType = 0;
  }

  void setChar(char a) 
  {
    variantType = 1;
    variantContent.v1 = a;
  }

  void setInt(int a)
  {
    variantType = 2;
    variantContent.v2 = a; 
  }

  // ... and so on

  bool getChar(char* pa)
  {
    if (variantType == 1)
    {
      *pa = variantContent.v1;
      return true;
    }

    return false; // Error reading a char where something else was stored
  }

  // ... and so on
}; 

Вы можете скопировать некоторую реализацию Variant в некоторый исходный код C ++ и перенести ее на C. Это не совсем то же самое, но похоже. И он несколько безопасен (по крайней мере, во время выполнения).

РЕДАКТИРОВАТЬ: гекса избил меня на секунду. И обратите внимание, что я не скомпилировал это, поэтому мой код может содержать опечатки.

1 голос
/ 30 июня 2011

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

1 голос
/ 30 июня 2011

номер

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

Хотя все члены объединения будут «содержать значение», отсутствует механизм, позволяющий определить, к какому типу данных он был изначально.

Если вам нужно это знать, то вам следует либо сохранить флаг, указывающий тип данных, либо вам не следует использовать объединение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...