Problems dereferensing my C structures (custom types)

F

Franz

Greetings,
I have created the following types:

typedef struct _tbl_certificate{
int cert_id;
char *cert_name;
}tbl_certificate;

typedef struct _cameraObj{
tbl_camera camera;
tbl_certificate *certificate;
}cameraObj;

I am having trouble accessing the certificate array in the cameraObj struct.

eg. cameraObj *camera;
camera->certificate[0].cert_id = 7;

This doesn't want to work. Any suggestions or ideas would be greatly appreciated!
Thanks
 
R

Richard Bos

typedef struct _tbl_certificate{
int cert_id;
char *cert_name;
}tbl_certificate;

Two notes:
* identifier names starting with _ are reserved for use by the
implementation, at file scope. This declaration probably is at file
scope. Therefore, _tbl_certificate is not a legal name for that struct.
Besides, it is perfectly legal to have a struct tbl_certificate,
typedef'ed to tbl_certificate; struct names are in a different namespace
from normal identifiers.
* some people would advise you not to use typedef in this situation at
all. You only gain a couple of keystrokes, and you lose transparence.
OTOH, you gain some data hiding, which may be good in some
circumstances.
So declare this as
typedef struct tbl_certificate {
int cert_id;
char *cert_name;
} tbl_certificate;
or even simply as
struct tbl_certificate {
int cert_id;
char *cert_name;
};

(Identifiers beginning with __ or _ and a capital letter are reserved
for the implementation regardless of scope, btw. I find it more
practical never to start a name with _ anyway, and never mind where it
happens to be allowed.)
typedef struct _cameraObj{
tbl_camera camera;
tbl_certificate *certificate;
}cameraObj;

Ditto here, of course.
I am having trouble accessing the certificate array in the cameraObj struct.

eg. cameraObj *camera;
camera->certificate[0].cert_id = 7;

This doesn't want to work. Any suggestions or ideas would be greatly appreciated!

Well, the error is not in what you posted - that part is OK, except for
the underscore. Presumably, the error is in the part of your code you
did not post; or perhaps it is in the part that you didn't even write,
but should have. You did remember to allocate memory for all those
pointers to point at, did you?

If you need more help, you'll have to help us help you. Describe exactly
what goes wrong; "this doesn't work" is an error report I expect from my
users, not from a fellow programmer. Whittle down your code to the
smallest example that demonstrates the problem, but is still compilable,
and post that.

Richard
 
J

Jens.Toerring

Franz said:
I have created the following types:
typedef struct _tbl_certificate{

No need to prepend an underscore. Never use them at the start of variable
or function names, you might get into conflicts with variables used by
your inplementation. And here's really no need for it, someting like

typedef struct my_name my_name;

works perfectly well.
int cert_id;
char *cert_name;
}tbl_certificate;
typedef struct _cameraObj{
tbl_camera camera;
tbl_certificate *certificate;
}cameraObj;
I am having trouble accessing the certificate array in the cameraObj struct.
eg. cameraObj *camera;
camera->certificate[0].cert_id = 7;
This doesn't want to work. Any suggestions or ideas would be greatly
appreciated!

You just have a created a pointer to a variable of type cameraObj, which
isn't pointing to anything you could use. So you first have to malloc()
memory for the structure. But you're still not done yet since now the
'certificate' member of your structure still points to some random
memory location, so you again have to allocate memory for the structure
it's supposed to point at. And then you may still have to allocate memory
for the 'cert_name' member of that structure...

Regards, Jens
 
C

CBFalconer

Franz said:
I have created the following types:

typedef struct _tbl_certificate{
int cert_id;
char *cert_name;
}tbl_certificate;

typedef struct _cameraObj{
tbl_camera camera;
tbl_certificate *certificate;
}cameraObj;

I am having trouble accessing the certificate array in the
cameraObj struct.

eg. cameraObj *camera;
camera->certificate[0].cert_id = 7;

This doesn't want to work. Any suggestions or ideas would be
greatly appreciated!

First, get rid of the leading _ in identifiers, which are not
legal for you to use. Then define whatever a tbl_camera is. Then
revise your code to something like:

cameraObj *camera;
...
if (!(camera = malloc(sizeof *camera))) {
exit(EXIT_FAILURE);
}
else if (!(camera->certificate =
malloc(sizeof *(camera->certificate))) {
exit(EXIT_FAILURE);
}
else {
camera->certificate.cert_id = 7;
}

and you may need another term to allocate certificate.name.
Replace the exit calls with whatever you want to handle such
memory lacks.
 
P

Peter Shaggy Haywood

Groovy hepcat Franz was jivin' on 17 Feb 2004 03:53:33 -0800 in
comp.lang.c.
Problems dereferensing my C structures (custom types)'s a cool scene!
Dig it!
Greetings,
I have created the following types:

typedef struct _tbl_certificate{
int cert_id;
char *cert_name;
}tbl_certificate;

typedef struct _cameraObj{
tbl_camera camera;
tbl_certificate *certificate;
}cameraObj;

I am having trouble accessing the certificate array in the cameraObj struct.

eg. cameraObj *camera;
camera->certificate[0].cert_id = 7;

This doesn't want to work. Any suggestions or ideas would be greatly appreciated!

The other answers were correct and you should pay heed to them, but
they missed one important thing. The -> operator dereferences the
pointer, but so does the [0] operator. You're dereferencing twice. You
need to do so only once. Remove the -> and use a dot in its place if
the pointer points at an array of tbl_certificate, or remove the [0]
otherwise. Ie.:

camera.certificate[0].cert_id = 7;
or
camera->certificate.cert_id = 7;

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 
A

Arthur J. O'Dwyer

[Franz wrote:]
typedef struct _tbl_certificate{
int cert_id;
char *cert_name;
}tbl_certificate;

typedef struct _cameraObj{
tbl_camera camera;
tbl_certificate *certificate;
}cameraObj;
cameraObj *camera;
camera->certificate[0].cert_id = 7;
The other answers were correct and you should pay heed to them, but
they missed one important thing. The -> operator dereferences the
pointer, but so does the [0] operator. You're dereferencing twice. You
need to do so only once.

Wrong. 'camera' is a pointer to '_cameraObj', and 'camera->certificate'
is a pointer to 'tbl_certificate'. Thus two dereferences are needed if
you want to access 'camera->certificate->cert_id'.

camera.certificate[0].cert_id = 7;

Doesn't type-check; 'camera' has no field 'certificate'.
camera->certificate.cert_id = 7;

Doesn't type-check; 'camera->certificate' has no field 'cert_id'.

-Arthur
 
P

Peter Nilsson

Peter "Shaggy" Haywood said:
Groovy hepcat Franz was jivin' on 17 Feb 2004 03:53:33 -0800 in
comp.lang.c.
Problems dereferensing my C structures (custom types)'s a cool scene!
Dig it!
Greetings,
I have created the following types:

typedef struct _tbl_certificate{
int cert_id;
char *cert_name;
}tbl_certificate;

typedef struct _cameraObj{
tbl_camera camera;
tbl_certificate *certificate;
}cameraObj;

I am having trouble accessing the certificate array in the cameraObj struct.

eg. cameraObj *camera;
camera->certificate[0].cert_id = 7;

This doesn't want to work. Any suggestions or ideas would be greatly
appreciated!

The other answers were correct and you should pay heed to them,

As should you. :)
but they missed one important thing. The -> operator dereferences the
pointer, but so does the [0] operator. You're dereferencing twice. You
need to do so only once. Remove the -> and use a dot in its place if
the pointer points at an array of tbl_certificate, or remove the [0]
otherwise. Ie.:

camera.certificate[0].cert_id = 7;
or
camera->certificate.cert_id = 7;

Both camera and certificate are pointer types in the quoted context above,
so the . operator is not an applicable to either.
 
L

Lewis Bowers

Peter said:
Peter "Shaggy" Haywood said:
Groovy hepcat Franz was jivin' on 17 Feb 2004 03:53:33 -0800 in
comp.lang.c.
Problems dereferensing my C structures (custom types)'s a cool scene!
Dig it!
Greetings,
I have created the following types:

typedef struct _tbl_certificate{
int cert_id;
char *cert_name;
}tbl_certificate;

typedef struct _cameraObj{
tbl_camera camera;
tbl_certificate *certificate;
}cameraObj;

I am having trouble accessing the certificate array in the cameraObj struct.

eg. cameraObj *camera;
camera->certificate[0].cert_id = 7;

This doesn't want to work. Any suggestions or ideas would be greatly
appreciated!

The other answers were correct and you should pay heed to them,

As should you. :)
but they missed one important thing. The -> operator dereferences the
pointer, but so does the [0] operator. You're dereferencing twice. You
need to do so only once. Remove the -> and use a dot in its place if
the pointer points at an array of tbl_certificate, or remove the [0]
otherwise. Ie.:

camera.certificate[0].cert_id = 7;
or
camera->certificate.cert_id = 7;

Both camera and certificate are pointer types in the quoted context above,
so the . operator is not an applicable to either.

The allocations are not shown. However, with the syntax
certificate[0], we can see that certificate is an array.
If it is an array of the struct pointers, then the -> operator is needed.
If it is an array of the struct objects, then the . operator is needed.

For an example of the later, see function AddCertificate in the following
example.

/* code untested */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

#define END 0

typedef struct _tbl_certificate{
int cert_id;
char *cert_name;
}tbl_certificate;

typedef struct _cameraObj{
char *camera_name;
tbl_certificate *certificate;
size_t cert_nr;
}cameraObj;

/* Prototypes */
char *CameraName(cameraObj *p, const char *name);
tbl_certificate *AddCertificate(cameraObj *p, int id,
const char *name);
void PrintInfo(cameraObj *p);
void FreeCertificates(cameraObj *p);
void FreeCamera(cameraObj *p);
int AddCameraInfo(cameraObj *p,const char *camera_name,
int cert_nr, ...);

int main(void)
{
cameraObj mycamera = {NULL};

CameraName(&mycamera, "Minolta");
AddCertificate(&mycamera, 326, "USDA");
AddCertificate(&mycamera, 4566,"Institute of Technology");
PrintInfo(&mycamera);

puts("Let's buy a new camera\n");
FreeCamera(&mycamera);
AddCameraInfo(&mycamera, "Kodak", /* Camera Name */
356,"MIT", /* Certificate 1 values */
221,"Computer Shopper", /*certificate 2 values */
END);
PrintInfo(&mycamera);

puts("Add another certificate\n");
AddCertificate(&mycamera,444,"Computer Magazine");
PrintInfo(&mycamera);

puts("The certificates have expired\n");
FreeCertificates(&mycamera);
PrintInfo(&mycamera);
FreeCamera(&mycamera);
return 0;
}

char *CameraName(cameraObj *p, const char *name)
{
char *tmp;

if((tmp = realloc(p->camera_name,strlen(name)+1)) != NULL)
{
strcpy(tmp,name);
p->camera_name = tmp;
}
return tmp;
}

tbl_certificate *AddCertificate(cameraObj *p, int id, const char *name)
{
tbl_certificate *tmp;

if((tmp = realloc(p->certificate,
(p->cert_nr+1)*sizeof *tmp)) == NULL) return NULL;
if((tmp[p->cert_nr].cert_name = malloc(strlen(name)+1)) == NULL)
return NULL;
strcpy(tmp[p->cert_nr].cert_name,name);
p->certificate = tmp;
strcpy(p->certificate[p->cert_nr].cert_name,name);
p->certificate[p->cert_nr++].cert_id = id;
return tmp;
}

void PrintInfo(cameraObj *p)
{
size_t i;

printf("Camera name: ");
if(p->camera_name)
puts(p->camera_name);
else puts("No Camera Name" );
if(!p->cert_nr) puts("No Certificates");
else
for(i = 0; i < p->cert_nr;i++)
printf("Certificate %u: ID: %d Name: %s\n",
i+1,p->certificate.cert_id,
p->certificate.cert_name);
putchar('\n');
return;
}

void FreeCertificates(cameraObj *p)
{
size_t i;

for(i = 0; i < p->cert_nr; i++)
free(p->certificate.cert_name);
free(p->certificate);
p->certificate = NULL;
p->cert_nr = 0;
return;
}

void FreeCamera(cameraObj *p)
{
FreeCertificates(p);
free(p->camera_name);
p->camera_name = NULL;
return;
}

int AddCameraInfo(cameraObj *p,const char *camera_name,
int cert_nr, ...)
{
size_t cnt;
int id;
const char *cert_name;
va_list marker;

if(!CameraName(p,camera_name)) return 0;
va_start(marker,cert_nr);
for(cnt = 0, id = cert_nr; id != END; cnt++,
id = va_arg(marker,int))
{
cert_name = va_arg(marker,const char *);
if(!AddCertificate(p,id,cert_name))
{
FreeCamera(p);
return 0;
}
}
p->cert_nr = cnt;
va_end(marker);
return 1;
}
 
A

Arthur J. O'Dwyer

Peter said:
Peter "Shaggy" Haywood said:
Groovy hepcat Franz was jivin' on 17 Feb 2004 03:53:33 -0800

typedef struct _tbl_certificate{
int cert_id;
char *cert_name;
}tbl_certificate;

typedef struct _cameraObj{
tbl_camera camera;
tbl_certificate *certificate;
}cameraObj;
camera.certificate[0].cert_id = 7;
or
camera->certificate.cert_id = 7;

Both camera and certificate are pointer types in the quoted context above,
so the . operator is not an applicable to either.

The allocations are not shown. However, with the syntax
certificate[0], we can see that certificate is an array.

The calls to 'malloc' (assuming that's what you meant) have nothing
to do with the case. With the declaration

tbl_certificate *certificate;

we can see that 'certificate' is a pointer to 'struct _tbl_certificate'.
That's all we need to know in order to construct correctly typed
expressions in C.
If it is an array of the struct pointers, then the -> operator is needed.
If it is an array of the struct objects, then the . operator is needed.

'certificate' is a pointer to struct.
For an example of the later, see function AddCertificate in the following
example.

Your syntax looks good. I didn't look very closely, because it's
still early morning to me (hey, 1:30 is early on a Sunday at CMU! ;)
and the code is pretty dense.
tbl_certificate *AddCertificate(cameraObj *p, int id, const char *name)
{
tbl_certificate *tmp;

if((tmp = realloc(p->certificate,
(p->cert_nr+1)*sizeof *tmp)) == NULL) return NULL;
if((tmp[p->cert_nr].cert_name = malloc(strlen(name)+1)) == NULL)
return NULL;

You've got here a memory leak (the memory pointed to by 'tmp')
and a disaster waiting to happen (the memory pointed to by
'p->certificate' is now free'd, but 'p->certificate' is not NULLed).
strcpy(tmp[p->cert_nr].cert_name,name);
p->certificate = tmp;
strcpy(p->certificate[p->cert_nr].cert_name,name);
p->certificate[p->cert_nr++].cert_id = id;
return tmp;
}

-Arthur
 
L

Lewis Bowers

Arthur J. O'Dwyer said:
tbl_certificate *AddCertificate(cameraObj *p, int id, const char *name)
{
tbl_certificate *tmp;

if((tmp = realloc(p->certificate,
(p->cert_nr+1)*sizeof *tmp)) == NULL) return NULL;
if((tmp[p->cert_nr].cert_name = malloc(strlen(name)+1)) == NULL)
return NULL;

You've got here a memory leak (the memory pointed to by 'tmp')
and a disaster waiting to happen (the memory pointed to by
'p->certificate' is now free'd, but 'p->certificate' is not NULLed).

It will not be a memory leak the way it was used here.. p->certificate is not
freed.
If the malloc call should fail the size of p->certificate remains unchanged.
It will have been allocated to one additional element that will not be used,
but the count is correct and any additional attempts to realloc will not be
adversely
affected. However, there is the potential for someone to use the return value and
assign it to the certificate pointer causing a memory leak and diseaster on an
allocation
failure. Perhaps a change of return type would solve this potential problem.
After all, the return type need only be used to indicate a successful allocation
or not.

strcpy(tmp[p->cert_nr].cert_name,name);
p->certificate = tmp;
strcpy(p->certificate[p->cert_nr].cert_name,name);

However, here we have two strcpy. They are both doing the same thing. One or the
other should be removed.
p->certificate[p->cert_nr++].cert_id = id;
return tmp;
}
 
P

Peter Shaggy Haywood

Groovy hepcat Arthur J. O'Dwyer was jivin' on Sun, 22 Feb 2004
04:31:25 -0500 (EST) in comp.lang.c.
Re: Problems dereferensing my C structures (custom types)'s a cool
scene! Dig it!
[Franz wrote:]
typedef struct _tbl_certificate{
int cert_id;
char *cert_name;
}tbl_certificate;

typedef struct _cameraObj{
tbl_camera camera;
tbl_certificate *certificate;
}cameraObj;
cameraObj *camera;
camera->certificate[0].cert_id = 7;
The other answers were correct and you should pay heed to them, but
they missed one important thing. The -> operator dereferences the
pointer, but so does the [0] operator. You're dereferencing twice. You
need to do so only once.

Wrong. 'camera' is a pointer to '_cameraObj', and 'camera->certificate'
is a pointer to 'tbl_certificate'. Thus two dereferences are needed if
you want to access 'camera->certificate->cert_id'.

Blah! You're right. Apologies to the OP! Water on the brain, I
think. No, lack of sleep. Yeah, that's it. It's the workmen building a
house across the street, starting too early in the morning, waking me
up. Can't think, too tired. Insomnia.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 
E

E. Robert Tisdale

Franz said:
Greetings,
I have created the following types:
> cat main.c
#include <stdio.h>
#include <stdlib.h>

typedef int tbl_camera;

typedef struct tbl_certificate {
int cert_id;
char* cert_name;
} tbl_certificate;

typedef struct cameraObj {
tbl_camera camera;
tbl_certificate* certificate;
} cameraObj;

int main(int argc, char* argv[]) {
cameraObj* camera
= (cameraObj*)malloc(sizeof(cameraObj));
camera->certificate
= (tbl_certificate*)malloc(sizeof(tbl_certificate));
((camera->certificate)[0]).cert_id = 7;
fprintf(stdout, "%d = ((camera->certificate)[0]).cert_id\n",
((camera->certificate)[0]).cert_id);
free((void*)camera->certificate);
free((void*)camera);
return 0;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main
7 = ((camera->certificate)[0]).cert_id

works just fine for me.
 
G

goose

E. Robert Tisdale said:
Franz said:
Greetings,
I have created the following types:
cat main.c
#include <stdio.h>
#include <stdlib.h>

typedef int tbl_camera;

typedef struct tbl_certificate {
int cert_id;
char* cert_name;
} tbl_certificate;

typedef struct cameraObj {
tbl_camera camera;
tbl_certificate* certificate;
} cameraObj;

int main(int argc, char* argv[]) {
cameraObj* camera
= (cameraObj*)malloc(sizeof(cameraObj));

no check for the return value of malloc?
why the cast?
[to OP] try this instead:

cameraObj *camera = malloc (sizeof *camera);
if (camera==NULL) {
/* handle error here,
and return
*/
}

now isn't that much neater? as a bonus, you also make sure
that your application does not crash and leave the user
frustrated, but instead fails gracefully (and perhaps
letting him save his work before it exits). Using sizeof
on the variable is always much better from a maintenance
viewpoint than using sizeof on the type.
camera->certificate
= (tbl_certificate*)malloc(sizeof(tbl_certificate));

do this instead, for the same reasons above:

camera->certificate = malloc (sizeof *camera->certificate);
if (camera->certificate==NULL) {
free (camera);
/* handle error and return */
}
((camera->certificate)[0]).cert_id = 7;
fprintf(stdout, "%d = ((camera->certificate)[0]).cert_id\n",
((camera->certificate)[0]).cert_id);
free((void*)camera->certificate);

the (void*) is not needed, and adds unnecessary clutter. the
following is perfectly legal:

free (camera->certificate);
free((void*)camera);

free (camera);
return 0;
}
gcc -Wall -std=c99 -pedantic -o main main.c
./main
7 = ((camera->certificate)[0]).cert_id

works just fine for me.

however that does not necessarily constitute "working fine".

hand
goose,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,310
Messages
2,571,603
Members
48,419
Latest member
EstelaCout

Latest Threads

Top