C宏-返回指针或为传递给宏的指针赋值

C宏-返回指针或为传递给宏的指针赋值,c,object,pointers,macros,C,Object,Pointers,Macros,我正在尝试编写“对象”样式的C代码,因为我需要使用不同的参数多次声明同一个对象。除了返回或指定指向所创建对象的指针外,其他一切都正常工作。我已经搜索并找到了几个例子,但没有一个是有效的 这就是有效的方法 头文件: #ifndef _OBJECT_H_ #define _OBJECT_H_ typedef struct { uint8_t* Buffer_PU8; uint8_t Index_U8; }TParameters_S; typedef struct { ui

我正在尝试编写“对象”样式的C代码,因为我需要使用不同的参数多次声明同一个对象。除了返回或指定指向所创建对象的指针外,其他一切都正常工作。我已经搜索并找到了几个例子,但没有一个是有效的

这就是有效的方法

头文件:

#ifndef _OBJECT_H_
#define _OBJECT_H_

typedef struct
{
    uint8_t* Buffer_PU8;
    uint8_t Index_U8;
}TParameters_S;

typedef struct
{
    uint8_t ID_U8;
    TParameters_S* Parameters_PS;
}TObject_S;

#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \

#endif  // _OBJECT_H_
#define NEW_OBJECT(id, size, handle) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    handle = &Object_S##id; \ <----- This does not work
#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    &Object_S##id; \ <----- This does not work
#define NEW_OBJECT(id, size, handle) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    static const TObject_S* __attribute__((used, section("my_objects_pointers"))) handle = &Object_S##id; \ <----- This works
#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) id = { \
        &Parameters_S##id \
    }; \

#define GET_OBJECT(id) (TObject_S*)&id
源文件:

#incldue "object.h"

typedef enum
{
    OBJECT1_E,
    OBJECT2_E,
}TObjects_E;

NEW_OBJECT(OBJECT1_E, 10);
NEW_OBJECT(OBJECT2_E, 20);

void function(void)
{
}
TObject_S* object1_PS;
TObject_S* object1_PS;

// therefore does not work
NEW_OBJECT(OBJECT1_E, 10, object1_PS);
NEW_OBJECT(OBJECT2_E, 20, object2_PS);

void function(void)
{
    // Then operate on the object (and therefore this does not work)
    object1_PS->Parameters_PS->Buffer_PS[object1_PS->Parameters_PS->Index_U8];
}
// therefore this does not work
TObject_S* object1_PS = NEW_OBJECT(OBJECT1_E, 10, object1_PS);
TObject_S* object1_PS = NEW_OBJECT(OBJECT2_E, 20, object2_PS);

void function(void)
{
    // Then operate on the object (and therefore this does not work)
    object1_PS->Parameters_PS->Buffer_PS[object1_PS->Parameters_PS->Index_U8];
}
TObject_S* object1_PS;
TObject_S* object1_PS;

// therefore this works
NEW_OBJECT(OBJECT1_E, 10, object1_PS);
NEW_OBJECT(OBJECT2_E, 20, object2_PS);

void function(void)
{
    // Then operate on the object (and therefore this works)
    object1_PS->Parameters_PS->Buffer_PS[object1_PS->Parameters_PS->Index_U8];
}
NEW_OBJECT(OBJECT1, 10);

const TObject_S* object1_PS = (TObject_S*)GET_OBJECT(OBJECT1);

void function(void)
{
    object1_PS->Parameters_PS->Buffer_PS[object1_PS->Parameters_PS->Index_U8];
}
这很好,在“my_对象”部分创建了两个“对象”。每个对象具有不同大小的缓冲区


但是我想得到一个指向这个对象的指针,这样我就可以对它进行操作了。我可以在“my_objects”部分中搜索对象并指向它,但是如果我可以在编译时指定一个指向该对象的指针,那就太好了。这样我就不必浪费时间或代码空间来搜索对象

因此,我尝试过这个方法,但它不起作用(希望它将对象指针指定给“句柄”):

头文件:

#ifndef _OBJECT_H_
#define _OBJECT_H_

typedef struct
{
    uint8_t* Buffer_PU8;
    uint8_t Index_U8;
}TParameters_S;

typedef struct
{
    uint8_t ID_U8;
    TParameters_S* Parameters_PS;
}TObject_S;

#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \

#endif  // _OBJECT_H_
#define NEW_OBJECT(id, size, handle) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    handle = &Object_S##id; \ <----- This does not work
#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    &Object_S##id; \ <----- This does not work
#define NEW_OBJECT(id, size, handle) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    static const TObject_S* __attribute__((used, section("my_objects_pointers"))) handle = &Object_S##id; \ <----- This works
#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) id = { \
        &Parameters_S##id \
    }; \

#define GET_OBJECT(id) (TObject_S*)&id
我也尝试过这个,希望它能返回一个指向对象的指针(我想我在这里是在冒险):

头文件:

#ifndef _OBJECT_H_
#define _OBJECT_H_

typedef struct
{
    uint8_t* Buffer_PU8;
    uint8_t Index_U8;
}TParameters_S;

typedef struct
{
    uint8_t ID_U8;
    TParameters_S* Parameters_PS;
}TObject_S;

#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \

#endif  // _OBJECT_H_
#define NEW_OBJECT(id, size, handle) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    handle = &Object_S##id; \ <----- This does not work
#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    &Object_S##id; \ <----- This does not work
#define NEW_OBJECT(id, size, handle) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    static const TObject_S* __attribute__((used, section("my_objects_pointers"))) handle = &Object_S##id; \ <----- This works
#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) id = { \
        &Parameters_S##id \
    }; \

#define GET_OBJECT(id) (TObject_S*)&id
这是可行的,但我认为它为每个对象创建了两个指针。虽然我只能看到地图文件中每个对象的一个指针:

头文件:

#ifndef _OBJECT_H_
#define _OBJECT_H_

typedef struct
{
    uint8_t* Buffer_PU8;
    uint8_t Index_U8;
}TParameters_S;

typedef struct
{
    uint8_t ID_U8;
    TParameters_S* Parameters_PS;
}TObject_S;

#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \

#endif  // _OBJECT_H_
#define NEW_OBJECT(id, size, handle) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    handle = &Object_S##id; \ <----- This does not work
#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    &Object_S##id; \ <----- This does not work
#define NEW_OBJECT(id, size, handle) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    static const TObject_S* __attribute__((used, section("my_objects_pointers"))) handle = &Object_S##id; \ <----- This works
#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) id = { \
        &Parameters_S##id \
    }; \

#define GET_OBJECT(id) (TObject_S*)&id

问题是你在全局范围内写作业。当
新对象
展开时,它会创建-

handle=&Object\u S0

对于第一个对象。这在C中是不允许的

您必须将此分配移动到主函数中,或在需要引用它的任何位置使用
&Object\u S0


您可以在函数中创建对象,这样就可以了。对象将静态创建,赋值将在运行时发生

可执行语句(如赋值语句)必须出现在函数中。这就是为什么

    handle = &Object_S##id; \ <----- This does not work
请注意,由于您将结构本身声明为
const
,因此指向它的指针需要适应这一点。还请注意,我已经翻转了
struct TParameters_
的元素初始值设定项的顺序,以匹配结构定义中似乎显而易见的意图

附录:

另外请注意,除非您确实希望为缓冲区和参数使用单独的变量,否则,假定您在文件范围内声明所有内容,您可以替换复合文字来实现更干净的名称空间:

#define NEW_OBJECT(id, size, handle) \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        .ID_U8 = id, .Parameters_PS = & (TParameters_S) { \
            .Buffer_PU8 = (uint8_t[]) { [size - 1] = 0 }, .Index_U8 = 0 } \
    }; \
    const TObject_S *handle = &Object_S##id;

您可以进一步消除
对象*
变量,只保留句柄指针作为声明变量,但我不知道您可以将属性应用于复合文本。

好的,通过上面的注释(Henning和Ajay),我设法想出了一个解决方案

问题是该对象需要一个常量initilizer元素。所以我不能给那个范围内的变量赋值。但我可以用宏来克服它。因此,我所做的是:

头文件:

#ifndef _OBJECT_H_
#define _OBJECT_H_

typedef struct
{
    uint8_t* Buffer_PU8;
    uint8_t Index_U8;
}TParameters_S;

typedef struct
{
    uint8_t ID_U8;
    TParameters_S* Parameters_PS;
}TObject_S;

#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \

#endif  // _OBJECT_H_
#define NEW_OBJECT(id, size, handle) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    handle = &Object_S##id; \ <----- This does not work
#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    &Object_S##id; \ <----- This does not work
#define NEW_OBJECT(id, size, handle) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) Object_S##id = { \
        id, &Parameters_S##id \
    }; \
    static const TObject_S* __attribute__((used, section("my_objects_pointers"))) handle = &Object_S##id; \ <----- This works
#define NEW_OBJECT(id, size) \
    static uint8_t Buffer_AU8##id[size]; \
    static TParameters_S Parameters_S##id = { \
        0, Buffer_AU8##id \
    }; \
    static const TObject_S __attribute__((used, section("my_objects"))) id = { \
        &Parameters_S##id \
    }; \

#define GET_OBJECT(id) (TObject_S*)&id
源文件:

#incldue "object.h"

typedef enum
{
    OBJECT1_E,
    OBJECT2_E,
}TObjects_E;

NEW_OBJECT(OBJECT1_E, 10);
NEW_OBJECT(OBJECT2_E, 20);

void function(void)
{
}
TObject_S* object1_PS;
TObject_S* object1_PS;

// therefore does not work
NEW_OBJECT(OBJECT1_E, 10, object1_PS);
NEW_OBJECT(OBJECT2_E, 20, object2_PS);

void function(void)
{
    // Then operate on the object (and therefore this does not work)
    object1_PS->Parameters_PS->Buffer_PS[object1_PS->Parameters_PS->Index_U8];
}
// therefore this does not work
TObject_S* object1_PS = NEW_OBJECT(OBJECT1_E, 10, object1_PS);
TObject_S* object1_PS = NEW_OBJECT(OBJECT2_E, 20, object2_PS);

void function(void)
{
    // Then operate on the object (and therefore this does not work)
    object1_PS->Parameters_PS->Buffer_PS[object1_PS->Parameters_PS->Index_U8];
}
TObject_S* object1_PS;
TObject_S* object1_PS;

// therefore this works
NEW_OBJECT(OBJECT1_E, 10, object1_PS);
NEW_OBJECT(OBJECT2_E, 20, object2_PS);

void function(void)
{
    // Then operate on the object (and therefore this works)
    object1_PS->Parameters_PS->Buffer_PS[object1_PS->Parameters_PS->Index_U8];
}
NEW_OBJECT(OBJECT1, 10);

const TObject_S* object1_PS = (TObject_S*)GET_OBJECT(OBJECT1);

void function(void)
{
    object1_PS->Parameters_PS->Buffer_PS[object1_PS->Parameters_PS->Index_U8];
}

所有的强制转换可能都不是必需的,但它是有效的。

“如果我能在编译时指定一个指向该对象的指针,那就太好了”-我想你真的不想这样做。您对环境的内存管理有这样的控制吗?为什么没有?每次我调用NEW_OBJECT时,编译器都会创建struct TObject的一个实例,链接器会将它放在“my_objects”部分。现在我只需要一个指向该对象的变量。它与指向结构的任何其他变量一样。这没什么错。只是提醒一下,
\define\u OBJECT\u H
是非法的。以下划线和大写字母开头的标识符在所有上下文中都是保留的。为什么不直接使用
&Object\u SOBJECT1\u E
作为指向对象的指针?“编译器将创建结构的单个实例”--不,它不会,它需要常量初始值设定项元素。不允许将变量分配给全局范围内的变量。但是我可以用另一个宏来克服它?你也可以在宏中移动变量的声明。基本上,您在问题的最后一个方法中做了什么,然后删除了指针的额外声明
新对象之前…
只是冗余还是事实错误?这不是同一个变量的不同定义吗?不,@AjayBrahmakshatriya,不是。允许对同一变量进行多个声明,前提是类型兼容,最多一个声明有一个初始值设定项,并且满足关于声明链接的一些其他要求(包括变量有链接)。@JohnBollinger关于您的附录,这会不会将参数及其成员设置为const?既然对象是常量?我明确地这样声明它们,这样它们就不是常量。@user668773,复合文字替代方法不会产生任何尚未成为常量的
const
。复合文字表示可修改的对象(与字符串文字不同),因此无论哪种方式,
const
都是对象id和指向参数的指针。参数本身是可修改的——索引、缓冲区指针和缓冲区元素。还要注意的是,尽管句柄指向一个
const
结构,但它本身(指针)是可修改的。也许这只是我的傲慢,@AjayBrahmakshatriya,但从上下文和语气来看,我把它作为一个补充。我想他们的意思是,他们认为我在这方面很有知识,所以我必须愚蠢地去平衡其他事情。(但也许我应该被冒犯,因为他们认为我是一个全能天才的可能性很小?:-)