【问题标题】:C: Pointer to struct element inside the structC:指向结构内结构元素的指针
【发布时间】:2012-04-06 14:14:32
【问题描述】:

为了便于打印,我想创建一个指向我的结构元素的指针数组。我怎样才能做到这一点?我的尝试是在结构的最后一行。请注意,此结构具有除 int 之外的其他值,现在显示在此处。我只希望对整数进行这种索引。

struct status {
    int lastinputVac;
    int inputVac;

    int outputVac;

    /* The unit is % */
    int outputpower;

    int outputHz;

    /* The unit is % */
    int batterylevel;

    int temperatureC;

    int *ordered_values[] = { &lastinputVac, &inputVac, &outputVac, &outputpower, &outputHz, &batterylevel, &temperatureC };
}

【问题讨论】:

  • 没关系 - 编辑后的代码更有意义;)
  • 那么在结构中创建这种索引的正确方法是什么?
  • 虽然它使用 C++,但总体思路在我发布到上一个问题的answer 中得到了展示。您显然需要将std::string 更改为char *,并将cout 更改为printf,但使用offsetof 获得的偏移量数组才是最重要的,并且将保持不变。

标签: c pointers struct


【解决方案1】:

咬紧牙关,编写额外的代码以使用结构成员访问权限打印它。为了节省几行代码而牺牲您的设计是不值得的。

假设有一天你必须在库中公开这个结构。你真的想用这个没有实际用途的奇怪指针数组来加载用户吗?

【讨论】:

  • 我能理解你的观点,并且部分同意。但是我还是很好奇是怎么做到的。
【解决方案2】:

所以问题是“我想创建一个指向我的结构元素的指针数组。”并提到元素可能不是 int。

我编写了一个通用解决方案,在安全性或语言一致性和设计方面可能还需要大量改进,但它显示了以下问题的一个解决方案。下面的代码计算结构的大小,假设结构的元素都是相同的大小,然后构造一个指向元素的指针数组,print_array 函数通过打印这些元素来迭代这些元素。我也可以重载 ostream

  #include "stdafx.h"

  struct status {
      int lastinputVac;
      int inputVac;
      int outputVac;

      /* The unit is % */
      int outputpower;

      int outputHz;

      /* The unit is % */
      int batterylevel;

      int temperatureC;
};

//template<typename T>
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>

// hide this into a library 
template<typename T>
size_t build_array(const status& val, T*** vecptr)
{
const size_t _size = sizeof(status) / sizeof(int);
*vecptr = (T**)malloc( sizeof(T*) *_size );

for (size_t i = 0; i < _size; ++i) {
    (*vecptr)[i] = ((T *)((&val)+i));
}
return _size;
}

template<typename T>
void free_array(T** vecptr)
{
free(vecptr);
}

template<typename T>
void print_array(T **vecptr, size_t size) 
{
for (size_t i = 0; i < size; i++)
    std::cout << *(*vecptr + i) << std::endl;
}

//T1 is the type of the struct and T2 is the type of the elements
template<typename T1, typename T2>
class PrintStruct
{
private:
    T2 **m_vecptr;
    size_t m_size;

public:
    PrintStruct(T1 t) {
        m_size = build_array<T2>(t, &m_vecptr);
        print_array(m_vecptr, m_size);
    }

    ~PrintStruct() {
        free_array(m_vecptr);
    }
 };

 int _tmain(int argc, _TCHAR* argv[])
 {
 status _status;
 _status.batterylevel = 1;
 _status.inputVac = 2;
 _status.lastinputVac = 3;
 _status.outputHz = 4;
 _status.outputpower = 5;
 _status.outputVac = 6;
 _status.temperatureC = 7;

 PrintStruct<status, int> _ps(_status);
 return 0;
 }

【讨论】:

  • 我同意。 :) 将发布另一个解决方案。
  • 用宏替换模板很容易。核心是用 C 语言编写的(编译为 c++)。它变成了一个衬里,您可以在其中轻松打印结构,提供约束。
【解决方案3】:

你不能独立于结构变量实例获取结构成员的地址; IOW,你必须做类似的事情

struct status foo;
int *ordered_values[] = {&foo.lastInputVac, &foo.inputVac, ...};

但是,鉴于您的所有结构成员都是ints,您可以做一些类型双关a la

int *ordered_values = (int *) &foo;
for (i = 0; i < 7; i++)
  printf("%d\n", ordered_values[i]);

应该工作;结构实例的地址与其第一个成员的地址相同,并且由于所有成员都是ints,因此不应该有任何对齐或填充问题。我不推荐这种做法,但出于您的目的,它应该足够好用。

【讨论】:

  • 只显示了结构的一部分。我里面还有其他变量。但只需要这种索引用于整数。谢谢!
  • @PeterSenna:在这种情况下,请忽略我写的内容;如果不是所有东西都是相同的类型,那么这个例子就行不通了。
【解决方案4】:

这样是不可能的。

在 C++ 中有一个成员指针(“相对”指针)的概念,这正是您真正需要的。

在您的情况和 C 中,我建议始终使用整数数组并命名索引

struct status {
   int values[7];
}
..
const int lastinputVac = 0;  // or upper case when you like, or use #define
..
status a;
a.values[lastinputVac] = 27;
int z = a.values[lastinputVac];

你明白了吗??

顺便说一句,你可以用联合来做这两种方法, 通过数组的索引提供具有名称和方式的编译访问

【讨论】:

    【解决方案5】:

    从阅读您的 cmets 来看,您的结构似乎有很多元素,但您只想打印其中的一些。以下是我的想法:

    1) 不要将此数组放入结构中!它是静态的——对于任何struct status,它永远不会改变,因此将它放在结构中既浪费又不直观。

    2) 您是否考虑过将这些值分离到它们自己的结构中?然后,您可以使用以下范例:

    enum status {
        LASTINPUT_VAC,
        INPUT_VAC,
        OUTPUT_VAC,
        OUTPUT_PWR,
        OUTPUT_HZ,
        BATT_LVL,
        TEMPERATURE,
        STATUS_MAX
    };
    
    struct system {
        char name[MAXNAME];
        long other_data;
        float coords[2];
        char *whatever_you_have_here;
        int status[STATUS_MAX];
    };
    

    然后打印/使用你引用它的一个:

    struct system sys;
    int temp = sys.status[TEMPERATURE];
    for (int i = 0; i < STATUS_MAX; i++)
        printf("%d\n", sys.status[i]);
    

    这可能不符合您的确切需求,但我只是想把它放在那里,作为您可以在 C 中做这种事情的另一种方式。干杯!

    【讨论】:

      【解决方案6】:

      我想到了另一种方法。 我的观察是,成员的顺序是正确的,但您可能希望通过索引轻松访问。

      但是警告:你必须关心填充。填充可能会错位整数。但是,在 int32 的情况下,我预计没有问题。

      有些人会认为这太 hacky,但是,这是可能的

      struct status {
        int lastinputVac;
        int inputVac;
      
        int outputVac;
      
      /* The unit is % */
        int outputpower;
      
        int outputHz;
      
        /* The unit is % */
        int batterylevel;
      
        int temperatureC;
      } stat;
      
      int* a = &stat;
      
      int maxIndex = (&stat.temperatureC - &stat.lastinputVac) / sizeof (stat); // should be 6
       // you could build named constants for that
      a[0]; // lastinputVac
      a[1]; // inputVac
      a[2]; // outputVac
      a[3]; // outputpower
      a[4]; // outputHz
      a[5]; // batterylevel
      a[6]; // temperatureC
      

      【讨论】:

        【解决方案7】:

        将结构与数组联合。请查阅有关对齐的编译器文档。

        union {
        
            struct {
               int someInt0;
               int someInt1;    
            }; //anonymous
        
            int arry[2];
        
        } thing;
        

        ~

        val0 = thing.someInt0; //structure access
        val1 = thing.arry[0]; //gcc, C18, XC8, and XC32 handle this with the top value indexed to 0
        
        if (val0 == val1) { 
            puts("this works");
        }
        

        【讨论】:

          猜你喜欢
          • 2021-02-02
          • 2017-01-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-01-29
          • 2015-09-11
          • 2012-07-16
          相关资源
          最近更新 更多