如何"延伸"在C中结构?

时间:2015-05-24 00:42:01

标签: c data-structures scope

我想根据某些值从文件中读取不同的数据结构。在某些解释语言中,我可以执行类似于下面的代码。在C ++中,我会扩展currentMsg类。但是出于某种原因我选择了C.我可以为每个案例编写两个单独的代码块。我还有其他选择吗?这个问题可能很愚蠢,但你对那个HTML家伙有什么期望呢。

(function message() {
    var ranNumber = Math.floor((Math.random() * 5) + 0);
    var randomMsg = [
      "string one",
      "string two",
      "string three",
      "string four",
      "string five"
    ];

    var currentMsg = randomMsg[Math.floor((Math.random() * 5) + 0)];
    var prevMsg = "";

    document.getElementById("intro").innerHTML = currentMsg;

    document.getElementById("intro").onclick = function() {
        var ranNum = Math.floor((Math.random() * 5) + 0);
        currentMsg = randomMsg[ranNum];
        if(prevMsg == currentMsg) {
            var anotherMsg = "";
            if(ranNum >= 0 && ranNum < 4) {
                anotherMsg = randomMsg[ranNum + 1];
            }
            else {
                anotherMsg = randomMsg[ranNum - 1];
            }
            document.getElementById("intro").innerHTML = anotherMsg;
            prevMsg = anotherMsg; // set prevMsg to anotherMsg
        } else {
            document.getElementById("intro").innerHTML = currentMsg;
            prevMsg = currentMsg; // set prevMsg to currentMsg
        };
    };
})();

3 个答案:

答案 0 :(得分:2)

用另一个包裹它怎么样?

typedef struct structA{
  int x;
  int y;
}A;

typedef struct structB{
  A *a;
  int z;
}B;

注意:记住初始化structB内的A指针。

更新:另一个选择是使用两种类型的联合:

typedef struct structA{
  int x;
  int y;
}A;

typedef struct structB{
  int z;
}B;

union AB {
  A* a;
  B* b;
} ABUnion;

答案 1 :(得分:2)

由于struct的头部没有填充,因此共享相同(或兼容)第一个字段的两个struct与该部分兼容。例如,通过各种sockaddr类型使用该技巧(第一个字段是地址类型,其余字段取决于该字段的值)。

以下是如何在您描述的方案中使用此属性的示例:

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#define common_fields \
    int value; \
    bool is_plus

struct base_type {
    common_fields;
};

struct plus_type {
    common_fields;
    int plus_value;
};

static void print_struct (const struct base_type * const p) {
    (void) printf("value = %d\n", p->value);
    if (p->is_plus) {
        const struct plus_type * const plus = (struct plus_type *)p;
        (void) printf("plus_value = %d\n", plus->plus_value);
    }
}

int main (int argc, char *argv[]) {
    struct base_type *p;
    if (argc > 1) {
        p = malloc(sizeof(struct plus_type));
        p->is_plus = true;
    } else {
        p = malloc(sizeof(struct base_type));
        p->is_plus = false;
    }
    p->value = 6;
    if (p->is_plus) {
        ((struct plus_type *)p)->plus_value = atoi(argv[1]);
    }
    print_struct(p);
    free(p);
    return EXIT_SUCCESS;
}

common_fields宏用于避免两次输入公共字段。许多流行的编译器都有一个扩展,允许执行以下操作:

struct base_type {
    int value;
    bool is_plus;
}

struct plus_type {
    struct base_type;
    int plus_value;
};

clanggcc此扩展程序由-fms-extensions启用。

请注意,使用此技巧时,必须注意分配struct的正确大小。或者,您可以在char的末尾添加额外字段(例如,struct base_type数组),使其至少与struct plus_type(以及任何其他struct s一样大共享相同的基本类型),但在这种情况下,使用union解决方案可能会更好。

答案 2 :(得分:0)

以下建议的代码处理支柱大小和任何错误条件

struct shortStruct
{
    int field1;
};

struct longStruct
{
    int field1;
    int field2;
};

char buffer[sizeof(longStruct)+1];

memset( buffer, '\0', sizeof(longStruct) );
if ( 0x020b == options.signature  )
{
    byteCount = read( fd, buffer, sizeof( struct shortStruct ) );
}
else
{
    byteCount = read( fd, buffer, sizeof( struct longStruct );
}

switch( byteCount )
{
    case sizeof(longStruct):
        // process long struct fields
        break;

    case sizeof(shortStruct):
        // process short struct fields
        break;

    default:
        // process the error
        break;
} // end switch