This question already has answers here:
typedef pointer const weirdness
(6 answers)
Closed 8 years ago.
I have a struct type_s. Then I typedef a pointer to a struct type_s as type.
If I have a const struct type_s* then the compiler will correctly complain if an assignment is made to the struct member, as seen in function Test1(). But if I make a const type, which is a typedef for the same struct pointer the compiler will not complain and compile, function Test2().
typedef struct type_s* type ;
struct type_s
{
int a ;
} ;
void Test1( const struct type_s* t )
{
t->a = 123 ; //complains, ok
}
void Test2( const type t )
{
t->a = 123 ; //doesn't, it should in my oppinion
}
To me they are logically both the same thing. What am I missing?
Is the only solution to create another typedef for a constant pointer to that struct like this:
typedef const struct type_s* ctype ;
which will work correctly as in Test1().
What you're missing is that a const pointer is not the same thing as a pointer to a const object. You have one of each. A const pointer is a pointer whose stored address is not modifiable; a pointer to const is one which cannot be used to modify its referent.
They are not the same thing. const has different semantics when applied to the definition or declaration of a pointer variable and a non-pointer variable.
const struct type_s *t
The above statement defines t to be a pointer to an object of type const struct type_s. Here, const qualifies the type struct type_s of the object t points to, not the pointer t.
typedef struct type_s *type ;
The above statement defines an alias named type for the type struct type_s *.
const type t;
// equivalent to
type const t;
// equivalent to
struct type_s *const t;
The above statement defines t to be a constant object of type type. Here const qualifies the object. You cannot replace the typedef with its original type and reinterpret it as if it were a macro. The pointer information is embedded in the typedef and it will be treated as a non-pointer type.
Related
I have the following struct:
struct foo
{
...
char* cp;
};
And I want to pass a struct foo type pointer to a function, but I want the function to cast the pointer to const char* const cp, and I don't want the const qualifier as part of the definition of struct foo. Declaring the function as:
void func (const struct foo* foo_i);
will ensure the pointer cp is unchanged, but not the data it points to. Is there a way to declare the function so that the data is ensured to be read-only too?
What you describe is not possible.
Consider making cp of type const char*.
If I have created a C module that presents a handle to the user with a pointer to a forward declared struct, like so:
typedef struct FOO_Obj *FOO_Handle;
If I then declare function prototypes that use it as a const qualified parameter thusly:
void FOO_work(const FOO_Handle fooHandle);
How is the const-ness applied?
const struct FOO_Obj *FOO_Handle // A
struct FOO_Obj *const FOO_Handle // B
const struct FOO_Obj *const FOO_Handle // C
Or is it UB?
B. ( There is no undefined behavior with the code you presented. )
The function call
void FOO_work(const FOO_Handle fooHandle);
is equivalent to
void FOO_work(struct FOO_Obj* const fooHandle);
Variable fooHandle in the function will becode a const pointer to a non-const struct FOO_Obj object. You will not be able to add the const qualifier to fooHandle to make it a pointer to a const object.
Instead, if you want to have a pointer to a const object, and keep the struct hidden, you must make another typedef:
typedef const struct FOO_Obj* FOO_ConstHandle;
I am trying to access structure element via constant pointer. Program works like it should but I got warning 'intialization from incompatible pointer type' and '(near initalization for 'B.settings)'. I don't really know how to correctly initalize it. Can someone pls help me figure that out?
Here's my code :
It's just a snippet of larger part. Idea is to have access to structure variables x,y when moving via pointers to const structure. Hope that make sense.
#include <stdio.h>
#define PGM_STR(X) ((const char[]) { X })
struct SettingsStruct
{
unsigned int x;
unsigned int y;
}Settings;
struct constitem
{
const char * const text;
const struct constitem *next;
const struct SettingsStruct * settings;
};
struct constitem const A;
struct constitem const B = {PGM_STR("x"), &A, &Settings.x };
struct constitem const A = {PGM_STR("y"), &B, &Settings.y };
static const struct constitem *currMenuPtr=&A;
void main()
{
Settings.x = 1;
Settings.y = 2;
printf("%s\n",currMenuPtr->text);
printf("%d\n",*(currMenuPtr->settings));
currMenuPtr = currMenuPtr->next;
printf("%s\n",currMenuPtr->text);
printf("%d\n",*(currMenuPtr->settings));
}
In your code, Settings.x is an unsigned int, and therefore &Settings.x is an unsigned int *. You are trying to use it to initialize a value of type const struct SettingsStruct *. The compiler is quite right to complain -- what you are doing is highly questionable, and I suppose probably not what you actually mean to do. The same applies to Settings.y.
It looks like you could get the compiler to stop complaining (about that) by changing the type of the third element of struct constitem to unsigned int *. You'll have to judge whether that actually works for you in the larger scheme of your program, though.
There is also a problem with using &A in the initializer for variable B when A is not yet declared at the point where the initializer appears. Inasmuch as you also refer to B in A's initializer, you can't solve that by swapping the declaration order. If you really do want a circular chain of pointers, then the pointer values cannot be const, because at least one of them will need to be modified after initialization.
I have read other answers on this topic, but they didn't help me.
I am trying to initalize a struct but getting the following error msgs in C:
error: initializer element is not constant
error: (near initialization for 'resource01.resource.role')
For Url it works, it's just the role which is not working. And if I'm defining the role as char, I don't have any problems. What am I doing wrong?
static char const resource01Url[] = "/dummy";
static int const resource01Role = 2;
static struct RestResourceNode_S resource01 =
{
{
resource01Url,
resource01Role,
&DummyHandler_call
},
NULL
};
static struct RestResourcesManager_S resourcesManager =
{
&resource01, &resource01
};
The type RestResourceNode_S is defined:
struct RestResourceNode_S
{
RestResource_T resource;
struct RestResourceNode_S const *next;
}
and RestResource_t:
struct RestResource_S
{
char const *url;
int const *role;
retcode_t (*handle)(Msg_T *);
};
typedef struct RestResource_S RestResource_T;
The error means that you are using a non-constant expression to initialize a structure member.
The expression is resource01Role.
While it is declared as static and const it is not an initializer constant expression from the view of the C compiler. If you want to use it this way, you would have to define it as a preprocessor macro. In your case, const only points out to the compiler that the value of resource01Role will not change - it does not permit it to use the value during compile-time.
However, as #WhozCraig pointed out, the type of role is actually int const *, so you probably meant to write &resource01Role. Adress-of is a constant expression, so that would compile.
Since resource01Url is an array, the adress-of operator & is implicitly applied by the compiler, so it is constant.
I want to define a vector of struct. This vector should have the elements : user and role.
struct UserToRole_S
{
char user[SERVAL_HTTP_MAX_LEN_USER_NAME + 1];
unsigned int role;
};
typedef struct UserToRole_S UserToRole
#define ENDROLE 5
static UserToRole user_role[6] =
{
{"user5", ADMIN},
{"user4", GUEST},
{"user3", GUEST},
{"user2", GUEST},
{"user1", ADMIN},
{"andreea", ENDROLE},
};
UserToRole const *usertoroleTable[2] =
{
&user_role,
NULL
};
extern UserToRole const *usertoroleTable[];
But then I get the error: initialization from incompatible pointer type
What is wrong with my code? Definition of the vector?
You are missing typedef, you can't use the bare name of a structure as a type name in C.
Either add:
typedef struct UserToRole_S UserToRole_S;
or use:
static struct UserToRole_S user_role[] =
and so on, i.e. replace the bare name with the full struct UserToRole_S type name.