簡體   English   中英

C:指向結構內部結構元素的指針

[英]C: Pointer to struct element inside the struct

為了便於打印,我想創建一個指向我的結構元素的指針數組。 我怎樣才能做到這一點? 我的嘗試是在結構的最后一行。 請注意,此結構具有除 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 };
}

硬着頭皮寫額外的代碼,通過結構成員訪問來打印它。 為了節省幾行代碼而犧牲您的設計是不值得的。

想象一下,有一天你必須在庫中公開這個結構。 你真的想用這個沒有實際用途的奇怪指針數組來加載用戶嗎?

所以問題是“我想創建一個指向我的結構元素的指針數組”。 並提到元素可能不是 int。

我寫了一個通用解決方案,在安全性或語言一致性和設計方面可能還需要大量改進,但它顯示了以下問題的一個解決方案。 下面的代碼計算結構的大小,假設結構的元素都是相同的大小,然后構造一個指向元素的指針數組,print_array function 通過打印出這些元素來迭代它們。 我也可以重載 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 我會建議總是使用一個整數數組並且只是命名索引

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];

你明白了嗎?

順便說一句,您可以使用 union 來執行這兩種方法,提供帶有名稱的編譯訪問和通過數組索引的方法

您無法獨立於結構變量實例獲取結構成員的地址; IOW,你必須做類似的事情

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

但是,鑒於您的所有 struct 成員都是int s,您可以做一些類型雙關

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

應該有效; struct 實例的地址與其第一個成員的地址相同,並且由於所有成員都是int s,因此不應該有任何 alignment 或填充問題。 我不推薦這種做法,但就您的目的而言,它應該可以很好地工作。

從閱讀您的評論來看,您似乎對結構有很多元素,但您只想打印其中的一些。 這是我的想法:

1)不要把這個數組放在結構中! 它是 static——它不會因任何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 中執行此類操作的另一種方式。干杯!

我想到了另一種方法。 我的觀察是,成員的順序正確,但您可能希望通過索引輕松訪問。

但警告:你必須關心填充。 填充可能會使整數不對齊。 但是,在 int32 的情況下,我希望沒有問題。

有些人會認為這太老套了,但是,這是有可能的

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

將結構與數組聯合。 請查閱有關 alignment 的編譯器文檔。

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");
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM