1

I'm trying to learn more about kobject in linux kernel and while trying to write a module that uses such facility, I was getting error and warning message, so I've put down here the trimmed down version of the relevant data structure and the corresponding gcc's error and warning message.

$ gcc issue.c 
issue.c:30:1: error: initializer element is not constant
 } ;
 ^
issue.c:30:1: error: (near initialization for ‘first.attr’)
issue.c:34:1: error: initializer element is not constant
 }; 
 ^
issue.c:34:1: error: (near initialization for ‘second.attr’)
issue.c:39:8: warning: initialization from incompatible pointer type [enabled by default]
 struct bin_attribute *my_bin_attrs[] = { &first_bin_attrs, &second_bin_attrs };
        ^
issue.c:39:8: warning: (near initialization for ‘my_bin_attrs[0]’) [enabled by default]
issue.c:39:8: warning: initialization from incompatible pointer type [enabled by default]
issue.c:39:8: warning: (near initialization for ‘my_bin_attrs[1]’) [enabled by default]

And the sample code:

#include <stdio.h>

struct attribute {
    const char      *name;
    unsigned short          mode;
};

struct bin_attribute {
    struct attribute    attr;
    unsigned int        size;
    void            *private;
};

struct attribute_group {
    const char      *name;
    struct attribute    **attrs;
    struct bin_attribute    **bin_attrs;
};

struct attribute first_attr = {
    .name = "FIRST"
}; 

struct attribute second_attr = {
    .name = "SECOND"
};

struct bin_attribute first = {
    .attr = first_attr
} ;

struct bin_attribute second = {
    .attr = second_attr
}; 

struct bin_attribute *first_bin_attrs = &first;
struct bin_attribute *second_bin_attrs = &second;

struct bin_attribute *my_bin_attrs[] = { &first_bin_attrs, &second_bin_attrs };

int main(void)
{
    struct attribute_group my_group = {
        .name = "xyz",
        .bin_attrs = my_bin_attrs,
    };

    return 0;
}
Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
Amit
  • 327
  • 1
  • 4
  • 12
  • possible duplicate of [Error "initializer element is not constant" when trying to initialize variable with const](http://stackoverflow.com/questions/3025050/error-initializer-element-is-not-constant-when-trying-to-initialize-variable-w) – Bernhard Barker Mar 30 '14 at 15:31
  • When you're getting an error message, you should **!!ALWAYS!!** Google the error message to try to figure it out before asking a [so] question about it. – Bernhard Barker Mar 30 '14 at 15:32
  • The "and other warning messages" is certainly less than ideal for a [so] question. One question should be about one error (/ question) (and they're errors, not warnings - there's a difference). Posts on [so] are intended to provide long-term value to many users. If you pollute a post by asking about many things, the chances of anyone coming across this post when looking for a specific one is slim, and if they do, they'll be left having to sift through all the other non-applicable information relating to the other errors. – Bernhard Barker Mar 30 '14 at 15:45

1 Answers1

0

You can't use the value of a variable as an initializer in a file-scope initializer.

You have:

struct attribute first_attr = {
    .name = "FIRST"
}; 

…

struct bin_attribute first = {
    .attr = first_attr
};

The second is generating the 'non-constant initializer' error because it is trying to use an expression, first_attr, that is not a compile-time constant. You might get away with it in C++; you can't in C.

You can use the address of a variable; that counts as a compile-time constant (resolved at link time), but not the value of a variable. Inside a function, you would be OK, too.

Either redesign the struct bin_attribute so that the attr member is a pointer, or forego the initialization you show.

The second set of errors is due to:

struct bin_attribute *first_bin_attrs = &first;
struct bin_attribute *second_bin_attrs = &second;

struct bin_attribute *my_bin_attrs[] = { &first_bin_attrs, &second_bin_attrs };

The type of &first_bin_attrs is struct bin_attribute **, so there is one too many levels of pointer in the initializer value. If you remove the &, the type is correct but you are back into the 'non-constant initializer' problem. If you add a * to the type of my_bin_attrs, you're in danger of becoming a Three Star Programmer, and you'll have to modify the code that uses my_bin_attrs.

The simple fix is:

struct bin_attribute *first_bin_attrs = &first;
struct bin_attribute *second_bin_attrs = &second;

struct bin_attribute *my_bin_attrs[] = { &first, &second };

But whether that's satisfactory depends on what you were trying to achieve.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278