Correct initialisation syntax with char in struct - struct

What is the correct syntax of a struct with char arrays ?
the nvsName gives me an error while compiling
And: is there another way to get initialize a value if the type is unknown ? Here I use the void*.
typedef struct
{
char nvsName[];
uint8_t type;
void* p;
} NVS_CONFIG;
NVS_CONFIG nvs = {'123',0,(void*)VdmConfig.configFlash.netConfig.staticIp};

your code contains multiple problems:
first : '123' is characther constant (see : wikipedia) not a string as you would expect with "123" and characther constant is an int.
second : nvsNames shoud be a pointer or have a constant size otherwise your code will not compile.
typedef struct
{
char * nvsName;
uint8_t type;
void* p;
} NVS_CONFIG;
NVS_CONFIG nvs = {"123",0,(void*)VdmConfig.configFlash.netConfig.staticIp};
should at least fix the probems you currently have.

Related

why typedef throwing error :(S) Initializer must be a valid constant expression

in f1.h header using typedef for structure. sample code snippet shown below
typedef struct{
int a;
union u
{
int x;
char y;
}xyz;
}mystruct;
In f2.h header using the structure mysturct to get the offset. Code snippet shown below
static mystruct ktt
//#define OFFSET_T(b, c) ((int*)((&((mystruct*)0)->b)) - (int*)((&((mystruct*)0)->c)))
#define OFFSET_T(b, c) ((char*) &ktt.b - (char *) &ktt.c)
static struct Mystruct1{
int n;
}mystruct1 = {OFFSET_T(xyz,a)};
when i'm doing compilation in AIX machine using xlc compiler it is throwing the error as "1506-221(S) Initializer must be a valid constant expression".
i tried both the macro's but both are getting same error. Is there anything wrong in f2.h macro while performing size of structure to get offset ??
The expression in question needs to be an arithmetic constant expression in order to be portable. Neither macro qualifies, since operands of pointer type are involved and arithmetic constant expressions are restricted such that those operands are not allowed. In C11, this is found in subclause 6.6 paragraph 8.
That said, the code using the first macro (source reproduced below) does compile on multiple versions of the xlc compiler on AIX.
typedef struct{
int a;
union u
{
int x;
char y;
}xyz;
}mystruct;
static mystruct ktt;
#define OFFSET_T(b, c) ((int*)((&((mystruct*)0)->b)) - (int*)((&((mystruct*)0)->c)))
//#define OFFSET_T(b, c) ((char*) &ktt.b - (char *) &ktt.c)
static struct Mystruct1{
int n;
}mystruct1 = {OFFSET_T(xyz,a)};
The compiler invocation I used was:
xlc offsetcalc.c -c -o /dev/null
The version information for one of the older versions I tried is:
IBM XL C/C++ for AIX, V10.1
Version: 10.01.0000.0021
The version information for one of the newest versions I tried is:
IBM XL C/C++ for AIX, V13.1.3 (5725-C72, 5765-J07)
Version: 13.01.0003.0004

Warning : comparison between pointer and integer

struct smt{
char *c;
};
int main(){
char *w="astring";
if(smt->c == w[0])
...do something
}
How do I fix the warning that I get in the if and what exacly causes it?
The warning shows up because you're comparing smt->c, which is char*, to w[0], which is a character (that for this comparison gets implicitly casted to int).
You probably meant comparing the first character like this:
if(smt->c[0] == w[0]) { ... }
If you want to compare full strings, use
if(strcmp(smt->c, w) == 0) { ... }
or even better, use strncmp if you know the maximum length the strings can have.
The error comes from the fact that often (almost always), you don't want to compare an adress (pointer) with a character.
You're comparing a char* c with a char 'a'. What you want to do is this I believe:
struct smt{
char *c;
};
int main(){
char *w="astring";
// Here smt->c returns a char*
// w[0] gets you the first character, so 'a'
if(strcmp(smt->c, w) == 0)
...do something
}
If you want to compare the first characters of both strings, you have to add [0] to smt->c

Error: this declaration has no storage class or type specifier ( Me making a simple struct. )

I was trying to make a simple struct to hold character stats.
This is what I came up with:
struct cStats
{
int nStrength;
int nIntelligence;
int nMedical;
int nSpeech;
int nAim;
};
cStats mainchar;
mainchar.nStrength = 10;
mainchar.nIntelligence = 10;
mainchar.nMedical = 10;
mainchar.nSpeech = 10;
mainchar.nAim = 10;
The mainchar. part is underlined red in visual studio, and when I mouse over it it shows this:
Error: this declaration has no storage class or type specifier
Any explanation of why it's doing this, and what I should be doing to fix it would be appreciated.
If this is C you should tag your question as such. cStats is a structure tag, not a type specifier. You need to declare mainchar as:
struct cStats mainchar;
If you wanted to use cStats as a type specifier you would define it as:
typedef struct
{
int nStrength;
int nIntelligence;
int nMedical;
int nSpeech;
int nAim;
} cStats;
If you did that your cStats mainchar would work.
Note that in C, char and character mean “ASCII alphanumeric character”, not “character in a play or game”. I suggest coming up with a different term for your program.
Another bit of advice; do not prefix your names with their data type; like nStrength for integer Strength. The compiler will tell you if you get your data types wrong, and if you ever need to change a type, for example to float nStrength to handle fractional Strengths, changing the name will be a big problem.
main(){
mainchar.nStrength = 10;
mainchar.nIntelligence = 10;
mainchar.nMedical = 10;
mainchar.nSpeech = 10;
mainchar.nAim = 10;}
These initialization should be written within the main() function.
Or else, write a init function and call it from main function.

lsmod showing module is used by -2

I am trying to pass command line parameters using following code
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
static int nilvar=0;
static int nilvar2=0;
int rollcalls[5];// = {0};
char classname[10];// = "math";
module_param_named (var,nilvar2,int,0644);
module_param (nilvar,int,0644);
module_param_array_named(present,rollcalls,int,5,0644);
module_param_string(subject,classname,10,0644);
int init_module(void)
{
printk(KERN_INFO"1) nilvar = %d\n 2) nilvar2 = %d",nilvar,nilvar2);
printk(KERN_INFO/*NOTICE*/"ROLLCALLS = %d ,%d ,%d ,%d",rollcalls[0],rollcalls[1],rollcalls[2],rollcalls[3]);
printk(KERN_INFO/*DEBUG*/"classname = %s",classname);
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Bye....\n");
}
MODULE_LICENSE("GPL");
after make ,I am passing my arguments by
insmod module1.ko var=5 nilvar=6 present=1 2 3 4 subject=physics
I don't know exactly what is happening but now lsmod shows module used by -2.
(actually no module is dependent on this module)
so where I am wrong ? and if we want to modify all this variables as a structure elements, then how to use module_param() macro for it?
#user3452214, instead of module_param_array_named(present, rollcalls, int, **5**, 0644); use module_param_array_named(present, rollcalls, int, **&count**, 0644); added one more variable i.e. static unsigned int count which keep count of the number written to the array. We need to pass the pointer as explained in the moduleparam.h, thus cannot pass numerical value for this parameter. It works fine!!!. Hope it solves your problem.
/**
* module_param_array_named - renamed parameter which is an array of some type
* #name: a valid C identifier which is the parameter name
* #array: the name of the array variable
* #type: the type, as per module_param()
* #nump: optional pointer filled in with the number written
* #perm: visibility in sysfs
*
* This exposes a different name than the actual variable name. See
* module_param_named() for why this might be necessary.
*/
#define module_param_array_named(name, array, type, nump, perm)

Passing struct to device driver through IOCTL

I am trying to pass a struct from user space to kernel space. I had been trying for many hours and it isn't working. Here is what I have done so far..
int device_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg){
int ret, SIZE;
switch(cmd){
case PASS_STRUCT_ARRAY_SIZE:
SIZE = (int *)arg;
if(ret < 0){
printk("Error in PASS_STRUCT_ARRAY_SIZE\n");
return -1;
}
printk("Struct Array Size : %d\n",SIZE);
break;
case PASS_STRUCT:
struct mesg{
int pIDs[SIZE];
int niceVal;
};
struct mesg data;
ret = copy_from_user(&data, arg, sizeof(*data));
if(ret < 0){
printk("PASS_STRUCT\n");
return -1;
}
printk("Message PASS_STRUCT : %d\n",data.niceVal);
break;
default :
return -ENOTTY;
}
return 0;
}
I have trouble defining the struct. What is the correct way to define it? I want to have int pIDs[SIZE]. Will int *pIDs do it(in user space it is defined like pIDs[SIZE])?
EDIT:
With the above change I get this error? error: expected expression before 'struct' any ideas?
There are two variants of the structure in your question.
struct mesg1{
int *pIDs;
int niceVal;
};
struct mesg2{
int pIDs[SIZE];
int niceVal;
};
They are different; in case of mesg1 you has pointer to int array (which is outside the struct). In other case (mesg2) there is int array inside the struct.
If your SIZE is fixed (in API of your module; the same value used in user- and kernel- space), you can use second variant (mesg2).
To use first variant of structure (mesg1) you may add field size to the structure itself, like:
struct mesg1{
int pIDs_size;
int *pIDs;
int niceVal;
};
and fill it with count of ints, pointed by *pIDs.
PS: And please, never use structures with variable-sized arrays in the middle of the struct (aka VLAIS). This is proprietary, wierd, buggy and non-documented extension to C language by GCC compiler. Only last field of struct can be array with variable size (VLA) according to international C standard. Some examples here: 1 2
PPS:
You can declare you struct with VLA (if there is only single array with variable size):
struct mesg2{
int niceVal;
int pIDs[];
};
but you should be careful when allocating memory for such struct with VLA

Resources