Accessing Union inside structure with pointer - c

I have the 2 structures definition below:
/* Ieee1609Dot2Data */
typedef struct Ieee1609Dot2Data {
Uint8_t protocolVersion;
struct Ieee1609Dot2Content *content;
asn_struct_ctx_t _asn_ctx;
} Ieee1609Dot2Data_t;
/* Ieee1609Dot2Content */
typedef struct Ieee1609Dot2Content {
Ieee1609Dot2Content_PR present;
union Ieee1609Dot2Content_u {
Opaque_t unsecuredData;
struct SignedData *signedData;
EncryptedData_t encryptedData;
Opaque_t signedCertificateRequest;
} choice;
asn_struct_ctx_t _asn_ctx;
} Ieee1609Dot2Content_t;
I want to Initialize the structure Ieee1609Dot2Data with a pointer to structure.
my main function :
int main(int ac, char **av) {
EtsiTs103097Data_t *EtsiTs103097Data; /* Type to encode */
asn_enc_rval_t ec; /* Encoder return value */
/* Encoding Buffer */
uint8_t buffer[128] ={0};
/* Allocate the EtsiTs103097Data */
EtsiTs103097Data = calloc(1, sizeof(EtsiTs103097Data_t)); /* not malloc! */
if(!EtsiTs103097Data) {
printf("Calloc Failed!");
exit(1);
}
uint8_t Msg_to_encode[] = "hello" ;
/* Initialize the EtsiTs103097Data memsbers */
EtsiTs103097Data->protocolVersion = 3;
EtsiTs103097Data->content->choice.unsecuredData.buf=(uint8_t*)Msg_to_encode; /* Runtime error */
...
}
there is a runtime error (Cannot access memory at address 0x8) at the line when I access choic union.
How can I access the union correctly?

EtsiTs103097Data->content is never assigned a value.

Related

expected struct foo* but argument is of type struct foo* for function pointers

I have two typedefs for function pointers and two structs, struct pipe_s and struct pipe_buffer_s defined as so:
typedef void (*pipe_inf_t)(struct pipe_buffer_s *);
typedef void (*pipe_outf_t)(struct pipe_buffer_s *);
struct
pipe_buffer_s
{
size_t cnt; /* number of chars in buffer */
size_t len; /* length of buffer */
uint8_t *mem; /* buffer */
};
struct
pipe_s
{
struct pipe_buffer_s buf;
uint8_t state;
pipe_inf_t in; /* input call */
pipe_outf_t out; /* output call */
};
In my implementation, I have a function that attempts to call the function in:
void
pipe_receive(struct pipe_s *pipe)
{
pipe_inf_t in;
in = pipe->in;
in(&pipe->buf);
}
But I am getting the strange error:
pipe.c:107:5: note: expected 'struct pipe_buffer_s *' but argument is of type 'struct pipe_buffer_s *'
This makes no sense to me. As far as I can tell, I haven't goofed up and tried to use a struct of undefined length because I'm only using pointers here. I think I may have done something wrong with my typedef...
Changing the typedef to typedef void (*pipe_inf_t)(int); and calling in(5) works just fine however.
I get the same error if I move in and out into the pipe_buffer_s struct and call them from there so location doesn't seem to matter.
Any ideas?
Add the definition of pipe_buffer_s before referring to it. This can be an incomplete type:
#include <stdlib.h>
#include <stdint.h>
struct pipe_buffer_s; // Incomplete definition
typedef void (*pipe_inf_t)(struct pipe_buffer_s *);
typedef void (*pipe_outf_t)(struct pipe_buffer_s *);
struct
pipe_buffer_s
{
size_t cnt; /* number of chars in buffer */
size_t len; /* length of buffer */
uint8_t *mem; /* buffer */
};
struct
pipe_s
{
struct pipe_buffer_s buf;
uint8_t state;
pipe_inf_t in; /* input call */
pipe_outf_t out; /* output call */
};
// In my implementation, I have a function that attempts to call the function in:
void
pipe_receive(struct pipe_s *pipe)
{
pipe_inf_t in;
in = pipe->in;
in(&pipe->buf);
}

trouble returning an array of a structure

I'm a newbie and I have a problem with array of type structure. I don't really know where to specify that the array is a pointer and where to not specify it. So whatever the combination I do with pointers in declaration and in calling of function involving this array of structure, it doesn't compile. Do you have any idea why ?
here is the code in question :
typedef struct{
char letter[7];
} player;
player init_player(){
player tab[2];
char letter_player1[4]={' ','a','b','c'};
char letter_player2[4]={' ','x','y','z'};
strcpy(tab[1].letter,letter_player1);
strcpy(tab[2].letter,letter_player2);
return *tab;
}
void displaying(player tab){
int position=1;
printf("%c\n",*tab[1].letter[position]);
}
int main(){
player tab=init_player(tab);
displaying(tab);
}
Thank you in advance !
How your code is wrong:
/* required #include (or function prototypes) are not written */
typedef struct{
char letter[7];
} player;
player init_player(){ /* the return type is not for returning arrays */
player tab[2];
/* no terminating null characters are placed, so cannot be used with strcpy() */
char letter_player1[4]={' ','a','b','c'};
char letter_player2[4]={' ','x','y','z'};
strcpy(tab[1].letter,letter_player1);
strcpy(tab[2].letter,letter_player2); /* only tab[0] and tab[1] are available, tab[2] is out-of-bounds */
return *tab; /* not the array but only the first element of the array is returned */
}
void displaying(player tab){ /* the argument type is not for getting arrays */
int position=1;
/* even if tab were an array(pointer), dereferencing is done via [] operator, so you don't need * here */
printf("%c\n",*tab[1].letter[position]);
}
int main(){
player tab=init_player(tab); /* the variable type is not for dealing with arrays */
displaying(tab);
}
How to fix:
/* add #include */
#include <stdio.h> /* for printf() */
#include <stdlib.h> /* for malloc(), free() and exit() */
#include <string.h> /* for strcpy() */
typedef struct{
char letter[7];
} player;
/* change return type to return a pointer */
player* init_player(){
/* you cannot use non-static local array, so instead dynamically allocate an array here */
player* tab = malloc(sizeof(*tab) * 2);
/* add terminating null characters (increase array size, and they will be automatically added) */
char letter_player1[5]={' ','a','b','c'};
char letter_player2[5]={' ','x','y','z'};
if (tab == NULL) exit(1); /* for in case the allocation failed */
/* use tab[0] and tab[1] instead of tab[1] and tab[2] */
strcpy(tab[0].letter,letter_player1);
strcpy(tab[1].letter,letter_player2);
return tab; /* return the (pointer to the first element of) array */
}
/* change argument type to get a pointer */
void displaying(player* tab){
int position=1;
/* remove extra * (indirection operator) */
printf("%c\n",tab[1].letter[position]);
}
int main(){
/* change variable type to store a pointer */
player* tab=init_player(tab);
displaying(tab);
free(tab); /* the array is dynamically allocated, so clean-up it */
}
You don't need the argument tab passed to init_player(),
but it is harmless because init_player() can accept any arguments and the arguments are not used.

How to define a struct function in a source file or struct itself

I'm confused about how I define a struct function in a source file or in the struct itself. Yes I have read a similar Stack Overflow question, but that asks if you can define a function declared in the struct itself. Basically in simple matters, I have this "NetworkDriver" struct:
typedef struct
{
char *name;
bool initialized;
int32_t status;
int (*initialize)(void);
} NetworkDriver;
As you can see, I'm trying to define the function pointer that has been initialized in the struct. How do we go about doing this?
The question being tagged as C (not C++) it should be noted that there is no such thing as a struct function in C. In the given code snippet, initialize is simply a data member of the struct typedef'd as NetworkDriver declared to be a pointer to a function that takes no arguments and returns an int.
The mechanics of defining and using the variable are the same as for any function pointer: it must be set to point to a function with the given prototype, then it can be called with the usual function syntax.
#include <stdio.h>
typedef struct
{
int (*initialize)(void);
} NetworkDriver;
int init(void)
{
printf("initializing...\n");
return 0;
}
int main(void)
{
NetworkDriver nd;
nd.initialize = init;
nd.initialize(); // prints 'initializing...'
return 0;
}
Not sure if I get the problem; what you did in your code fragment was declaring a type. There is no instance of this type yet that you could initialize; you need to declare an instance; either by adding it to the line at the end: }NetworkDriver var;, or by adding another line afterwards: NetworkDriver var;.
Either way, you can initialize this instance by adding ={"whatever",true,0,&function} to it; or specifically only that function pointer by adding a further line var.initialize = &funciton;.
Below is what I could get closest to what you are telling. I made some change (used int instead of bool), and also added one more function pointer in your NetworkDriver structure, and added parameters to the functions.
However, it seems you want each instance of NetworkDriver have its own initialize function. But what I have done is I have defined the initialize function once, and each instance of NetworkDriver have a pointer to it. Not exactly like what you are saying, but this is what I could think of.
As dxib has mentioned in his answer, the functions will still have to be explicitly called. I is not something like a constructor in C++. Also before calling, these functin pointers inside the structure have to be assigned the address of functions explicitly.
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define NO_ERR 10
#define NAME_ERR 11
#define INITIALIZED_ERR 12
typedef struct
{
char *name;
int initialized;
int32_t status;
int (*initialize)(void *, char *);
void (*disp_info)(void *); /* Note: one more func pointer */
}NetworkDriver;
/* Function prototype declarations */
int nd_init(void *ndr, char *name);
void nd_disp_info(void *ndr);
/* main: test NetworkDriver and nd_init */
int main(void)
{
NetworkDriver nd;
nd.initialized = FALSE;
nd.initialize = nd_init;
nd.disp_info = nd_disp_info;
if (nd.initialize(&nd, "foo")) { /* Initialize driver */
printf("Error: Initialization error\n");
exit(1);
}
nd.disp_info(&nd); /* display nd's info */
/* nd_init: initialize a NetworkDriver */
int nd_init(void *ndr, char *name)
{
NetworkDriver *nd;
nd = (NetworkDriver *) ndr;
if (!(nd->name = name)) {
nd->status = NAME_ERR;
return 1;
}
if (nd->initialized != TRUE) {
if (!(nd->initialized = TRUE)) {
nd->status = INITIALIZED_ERR;
return 1;
}
}
/* Successfully initialized */
nd->status = NO_ERR;
return 0;
}
/* nd_disp_info: display NetworkDriver info */
void nd_disp_info(void *ndr)
{
NetworkDriver *nd;
nd = (NetworkDriver *) ndr;
/* If this driver was not initialized without err */
if (nd->status != NO_ERR) {
printf("NetworkDriver was not initialized correctly\n");
return;
}
/* Print info */
printf("=== NetworkDriver info ===\n");
printf("Name: %s\n", nd->name);
printf("Initialized ? %s\n", nd->initialized == TRUE ? "TRUE" :
"FALSE");
printf("Status: %d\n", (int) nd->status);
}

OpenSSL RSA_size with EVP_PKEY

I have a question regarding RSA_size.
Version that crash on WIN32 but works on linux platforms :
...
EVP_PKEY* pPublicKey = null;
unsigned int uKeySize = 0;
const unsigned char *pData;
pData = a_publicKey->Key.Data; /* Key.Data = unsigned char *p containing the Key in a string version */
pPublicKey = d2i_PublicKey(EVP_PKEY_RSA, null, &pData, a_publicKey->Key.Length);
if(pPublicKey != null)
{
uKeySize = RSA_size(pPublicKey->pkey.rsa); //Crash
}
...
Version that work on win32 (not tested on linux but I suppose it works as well):
...
EVP_PKEY* pPublicKey = null;
RSA* pRsaPublicKey = null;
unsigned int uKeySize = 0;
const unsigned char *pData;
pData = a_publicKey->Key.Data; /* Key.Data = unsigned char *p containing the Key in a string version */
pPublicKey = d2i_PublicKey(EVP_PKEY_RSA, null, &pData, a_publicKey->Key.Length);
if(pPublicKey != null)
{
pRsaPublicKey = EVP_PKEY_get1_RSA(pPublicKey);
EVP_PKEY_free(pPublicKey);
uKeySize = RSA_size(pRsaPublicKey);
}
...
I do not understand why the first version crash. But when I look into the pkey.rsa structure, values are not the same as in the RSA pointer in the 2nd version.
Any ideas ?
I looked into EVP_PKEY struct and it seems that WIN32 and linux version are different...
So I guess i am using a really old one for my WIN32.
WIN32 version :
struct evp_pkey_st
{
int type;
int save_type;
int references;
union {
char *ptr;
#ifndef OPENSSL_NO_RSA
struct rsa_st *rsa; /* RSA */
#endif
#ifndef OPENSSL_NO_DSA
struct dsa_st *dsa; /* DSA */
#endif
#ifndef OPENSSL_NO_DH
struct dh_st *dh; /* DH */
#endif
#ifndef OPENSSL_NO_EC
struct ec_key_st *ec; /* ECC */
#endif
} pkey;
int save_parameters;
STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
} /* EVP_PKEY */;
linux :
struct evp_pkey_st
{
int type;
int save_type;
int references;
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *engine;
union {
char *ptr;
#ifndef OPENSSL_NO_RSA
struct rsa_st *rsa; /* RSA */
#endif
#ifndef OPENSSL_NO_DSA
struct dsa_st *dsa; /* DSA */
#endif
#ifndef OPENSSL_NO_DH
struct dh_st *dh; /* DH */
#endif
#ifndef OPENSSL_NO_EC
struct ec_key_st *ec; /* ECC */
#endif
} pkey;
int save_parameters;
STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
} /* EVP_PKEY */;

wrap/comment comments

I copy this struct
typedef struct SDL_Surface {
Uint32 flags; /* Read-only */
SDL_PixelFormat *format; /* Read-only */
int w, h; /* Read-only */
Uint16 pitch; /* Read-only */
void *pixels; /* Read-write */
SDL_Rect clip_rect; /* Read-only */
8 int refcount; /* Read-mostly */
/* This structure also contains private fields not shown
here */} SDL_Surface;
and tried to comment(wrap) out with /* and */ and beginning and end of the codes but it wouldn't work.
/*
typedef struct SDL_Surface { //only commented out this line
Uint32 flags; /* Read-only */
SDL_PixelFormat *format; /* Read-only */
int w, h; /* Read-only */
Uint16 pitch; /* Read-only */
void *pixels; /* Read-write */
SDL_Rect clip_rect; /* Read-only */
8 int refcount; /* Read-mostly */
/* This structure also contains private fields not shown
here */} SDL_Surface;
*/
Can anyone help me?
Use
#if 0
blah
#endif
to "comment out" large blocks of code like that. It also has the benefit of being nestable.
(The reason /* and */ aren't working is because once inside a comment, the first */ will end it, so /* blah /* explanation */ more */ will end after explanation, not more)
Nesting comments doesn't work, but you can have the preprocessor skip the struct
#if 0
typedef struct SDL_Surface {
Uint32 flags; /* Read-only */
SDL_PixelFormat *format; /* Read-only */
int w, h; /* Read-only */
Uint16 pitch; /* Read-only */
void *pixels; /* Read-write */
SDL_Rect clip_rect; /* Read-only */
8 int refcount; /* Read-mostly */
/* This structure also contains private fields not shown
here */} SDL_Surface;
#endif

Resources