Querry aoubt struct including character strings pointer

B

bowlderyu

Hello, all.
If a struct contains a character strings, there are two methods to
define the struct, one by character array, another by character pointer.
E.g,
//Program for struct includeing character strings, test1.c

#include <stdio.h>
#define LEN 20

struct info {
char first[LEN];
char last[LEN];
int age;
};

struct pinfo {
char * first;
char * last;
int age;
};

int main(void)
{
struct info one = {"Opw", "Cde", 22};
struct pinfo two = {"Tydu", "Gqa", 33};
printf("%s %s is %d years old.\n", one.first, one.last, one.age);
printf("%s %s is %d years old.\n", two.first, two.last, two.age);
return 0;
}

//end test1.c

It can work.I know a little,but not very detail that the second struct pinfo is not good
in the above code. E.g, if the struct pinfo two is defined as an array
two[1] in the main function, it can not work. I just want to know the
reason in detail.

The better way to avoid this problem is malloc() and another pointer
point to the struct, and copy the strings, then free it. Is it right?

Thank you.

bowderyu
 
I

Ian Collins

bowlderyu said:
Hello, all.
If a struct contains a character strings, there are two methods to
define the struct, one by character array, another by character pointer.
E.g,
//Program for struct includeing character strings, test1.c

#include <stdio.h>
#define LEN 20

struct info {
char first[LEN];
char last[LEN];
int age;
};

struct pinfo {
char * first;
char * last;
int age;
};

int main(void)
{
struct info one = {"Opw", "Cde", 22};
struct pinfo two = {"Tydu", "Gqa", 33};
printf("%s %s is %d years old.\n", one.first, one.last, one.age);
printf("%s %s is %d years old.\n", two.first, two.last, two.age);
return 0;
}

//end test1.c

It can work.I know a little,but not very detail that the second struct pinfo is not good
in the above code. E.g, if the struct pinfo two is defined as an array
two[1] in the main function, it can not work. I just want to know the
reason in detail.
It will work fine.

The answer to your question depends on your definition of "not good".
The first form is OK if you want mutable strings with a known maximum
length. The second is OK if you want constant strings and would be
safer if changed to

struct pinfo {
const char * first;
const char * last;
int age;
};
The better way to avoid this problem is malloc() and another pointer
point to the struct, and copy the strings, then free it. Is it right?
Which problem are you trying to avoid?
 
B

bowlderyu

const char *, good sugesstion.

I don't know why it can not work for the case of two[1], so I want to
avoid using char array. But now, it seems fine.

Would you please give more explanation about it?
I mean for why not safe for non-constant strings.

I am thinking about, seems clearly.

Now, I have to leave.

Anyway, thank you .
bowlderyu said:
Hello, all.
If a struct contains a character strings, there are two methods to
define the struct, one by character array, another by character pointer.
E.g,
//Program for struct includeing character strings, test1.c

#include <stdio.h>
#define LEN 20

struct info {
char first[LEN];
char last[LEN];
int age;
};

struct pinfo {
char * first;
char * last;
int age;
};

int main(void)
{
struct info one = {"Opw", "Cde", 22};
struct pinfo two = {"Tydu", "Gqa", 33};
printf("%s %s is %d years old.\n", one.first, one.last, one.age);
printf("%s %s is %d years old.\n", two.first, two.last, two.age);
return 0;
}

//end test1.c

It can work.I know a little,but not very detail that the second struct pinfo is not good
in the above code. E.g, if the struct pinfo two is defined as an array
two[1] in the main function, it can not work. I just want to know the
reason in detail.
It will work fine.

The answer to your question depends on your definition of "not good".
The first form is OK if you want mutable strings with a known maximum
length. The second is OK if you want constant strings and would be
safer if changed to

struct pinfo {
const char * first;
const char * last;
int age;
};
The better way to avoid this problem is malloc() and another pointer
point to the struct, and copy the strings, then free it. Is it right?
Which problem are you trying to avoid?
 
J

James Kuyper

bowlderyu said:
Hello, all.
If a struct contains a character strings, there are two methods to
define the struct, one by character array, another by character pointer.
E.g,
//Program for struct includeing character strings, test1.c

#include <stdio.h>
#define LEN 20

struct info {
char first[LEN];
char last[LEN];
int age;
};

struct pinfo {
char * first;
char * last;
int age;
};

int main(void)
{
struct info one = {"Opw", "Cde", 22};

In this case, you are creating arrays whose contents can be safely
modified, which are stored as part of 'one'.
struct pinfo two = {"Tydu", "Gqa", 33};

In this case, you are creating two unnamed arrays, whose contents cannot
be safely modified. You are storing pointers to those arrays in 'two'.
printf("%s %s is %d years old.\n", one.first, one.last, one.age);
printf("%s %s is %d years old.\n", two.first, two.last, two.age);
return 0;
}

//end test1.c

It can work.I know a little,but not very detail that the second struct pinfo is not good

There's no reason why it shouldn't be.
in the above code. E.g, if the struct pinfo two is defined as an array
two[1] in the main function, it can not work. I just want to know the
reason in detail.

If you change how you declare "two":

struct pinfo two[1] = {"Tydu", "Gqa", 33};

Then you also have to change how you use "two":

printf("%s %s is %d years old.\n",
two[0].first, two[0].last, two[0].age);

Assuming you made matching changes, as above, there's no reason why it
shouldn't work. Arrays of length 1 are generally pointless, but they're
perfectly legal.
The better way to avoid this problem is malloc() and another pointer
point to the struct, and copy the strings, then free it. Is it right?

Better in what sense? It's a lot more complicated than either method
you've shown above. I'd use the first method if the strings need to be
writable, but have a small fixed maximum length. I'd use the second
method if the strings don't need to be writable, though I would change
first and last to be "const char*" rather than "char*".

The only time I would ever use the malloc() approach is if the length of
the strings was not known at compile time, and has a large upper limit.
 
N

Nick Keighley

please put your reply after the text you are replying to.
Putting it before (as you did) is called "top posting".
I have rearranged your post.

Ian Collins said:
bowlderyu wrote:
If a struct contains a character strings, there are two methods to
define the struct, one by character array, another by character pointer.
E.g,
//Program for struct includeing character strings, test1.c
#include <stdio.h>
#define LEN 20
struct info {
char first[LEN];
char last[LEN];
int age;
};
struct pinfo {
char * first;
char * last;
int age;
};
int main(void)
{
struct info one = {"Opw", "Cde", 22};
struct pinfo two = {"Tydu", "Gqa", 33};
printf("%s %s is %d years old.\n", one.first, one.last, one.age);
printf("%s %s is %d years old.\n", two.first, two.last, two.age);
return 0;
}
//end test1.c
It can work.I know a little,but not very detail that the second struct
pinfo is not good
in the above code. E.g, if the struct pinfo two is defined as an array
two[1] in the main function, it can not work. I just want to know the
reason in detail.
It will work fine.
The answer to your question depends on your definition of "not good".
The first form is OK if you want mutable strings with a known maximum
length. The second is OK if you want constant strings and would be
safer if changed to
struct pinfo {
const char * first;
const char * last;
int age;
};
Which problem are you trying to avoid

const char *, good sugesstion.

I don't know why it can not work for the case of two[1], so I want to
avoid using char array. But now, it seems fine.

Would you please give more explanation about it?
I mean for why not safe for non-constant strings.

consider this:=

#include <stdio.h>
#define LEN 20

struct info {
char first[LEN];
char last[LEN];
int age;
};

struct pinfo {
char * first;
char * last;
int age;
};

int main(void)
{
struct info one = {"Opw", "Cde", 22};
struct pinfo two = {"Tydu", "Gqa", 33};

/* this is ok */
one.first[0] = 'X';

/* this is NOT ok! */
two.first[0] = 'X';

return 0;
}

one contains modifiable arrays. So its ok to modify them.
two points to string constants so it is *not* ok to modify
them. You cannot modify string constants.

This is ok:

int main(void)
{
struct pinfo two;
char first_arr[5] = "Tydu";

two.first = first_arr;
two.first[0] = 'X';

return 0;
}


I do not understand what you mean when you say "I don't know why it
can not work for the case of two[1], so I want to avoid using char
array. But now, it seems fine.".

Could you give an example which believe may be a problem.
 
J

Joachim Schmitz

Richard said:
Nick Keighley said:



s/cannot/must not/

This, as Nick already knows, is one of those situations where the C
language places a demand on the programmer rather than on the
implementation. Complying with that demand is, therefore, a matter of
self-discipline rather than implementation-imposed discipline. When
programmers ignore such demands, very often they get away with it. But
sometimes, they don't.

It's almost like driving on the wrong side of the road. If you live
in a relatively traffic-free area, you can actually drive on the
wrong side of the road for quite extended periods - but you only have
yourself to blame when you wrap yourself round a Mini Metro, with
quite possibly fatal consequences.

Happened to me once in the UK, driving on the right side (as opposed to
left, not wrong, but to me that's the same thing :cool:), for several miles on
an empty road in the very early hours of a day. Until a lorry approaching me
on my side stopped me... fortunatly no fatalities, not even a crash.
(It's not *quite* the same, because the police will enforce the law
if they happen to spot you. If you live anywhere near me, the chances
of that are pretty low, since the bobbies around here seem utterly
incapable of distinguishing their seating arrangements from their arm
joints. Nevertheless, the point stands.)

Some pedestrians were staring at me, but indeed no bobbies in sight...

Bye, Jojo
 
C

CBFalconer

Joachim said:
.... snip ...

Happened to me once in the UK, driving on the right side (as
opposed to left, not wrong, but to me that's the same thing :cool:),
for several miles on an empty road in the very early hours of a
day. Until a lorry approaching me on my side stopped me...
fortunatly no fatalities, not even a crash.

Way back when Sweden still drove on the left I visited there, and
the UK. I deliberately didn't take up any opportunities to drive,
because I expected habit would be over-riding. Even so, the London
traffic made mighty efforts to get me, as I looked left, saw no
traffic, and stepped out from the curb to be bashed from the right.

In Germany, France, Italy, Austria I could take a different
attitude. I did have problems with the German method of driving a
DKW, with a pure toggle action on the throttle.
 
J

Joachim Schmitz

CBFalconer said:
Way back when Sweden still drove on the left I visited there, and
the UK. I deliberately didn't take up any opportunities to drive,
because I expected habit would be over-riding. Even so, the London
traffic made mighty efforts to get me, as I looked left, saw no
traffic, and stepped out from the curb to be bashed from the right.

Been there, done that... on a dual carriageway (amongst others), thanks to a
great reaction of the driver I survived.
In Germany, France, Italy, Austria I could take a different
attitude. I did have problems with the German method of driving a
DKW, with a pure toggle action on the throttle.

Guess I'm to young for this, although I do recognize the brand name.

Bye, Jojo
 
M

Moi

CBFalconer wrote:

Guess I'm to young for this, although I do recognize the brand name.

Bye, Jojo

DKW used to be a brand of LKW.

But that was long before K&R.
:)
AvK
 
J

Joachim Schmitz

Moi said:
DKW used to be a brand of LKW.

Not quite correct. DKW also build cars and motorbikes.
(for the benefit of non-German speakers: LKW == LastKraftWagen == Truck,
Lorry)

And yes I knew that.

I just don't get Chucks point about "toggle action on the throttle",
probably because I never drove one and only vaguely remember having seem
them (born in '61)
But that was long before K&R.
:)
AvK

Bye, Jojo
 
D

Dik T. Winter

> DKW used to be a brand of LKW.

And of PKW. In the Netherlands it was frequently called "Duitse Kinder Wagen",
which German speakers would also be able to recognise.
 
B

bowlderyu

Nick Keighley said:
please put your reply after the text you are replying to.
Putting it before (as you did) is called "top posting".
I have rearranged your post.
Thank you very much for your work.
And it's a very good suggestion.
Ian Collins said:
bowlderyu wrote:
If a struct contains a character strings, there are two methods to
define the struct, one by character array, another by character pointer.
E.g,
//Program for struct includeing character strings, test1.c
#include <stdio.h>
#define LEN 20
struct info {
char first[LEN];
char last[LEN];
int age;
};
struct pinfo {
char * first;
char * last;
int age;
};
int main(void)
{
struct info one = {"Opw", "Cde", 22};
struct pinfo two = {"Tydu", "Gqa", 33};
printf("%s %s is %d years old.\n", one.first, one.last, one.age);
printf("%s %s is %d years old.\n", two.first, two.last, two.age);
return 0;
}
//end test1.c
It can work.I know a little,but not very detail that the second struct
pinfo is not good
in the above code. E.g, if the struct pinfo two is defined as an array
two[1] in the main function, it can not work. I just want to know the
reason in detail.
It will work fine.
The answer to your question depends on your definition of "not good".
The first form is OK if you want mutable strings with a known maximum
length. The second is OK if you want constant strings and would be
safer if changed to
struct pinfo {
const char * first;
const char * last;
int age;
};
Ok, the above words are help for me.
I made a mistake as to the struct pinfo two, so I want to avoid using
that struct. But now, for me, it is not a problem.
const char *, good sugesstion.

I don't know why it can not work for the case of two[1], so I want to
avoid using char array. But now, it seems fine.

Would you please give more explanation about it?
I mean for why not safe for non-constant strings.

consider this:=

#include <stdio.h>
#define LEN 20

struct info {
char first[LEN];
char last[LEN];
int age;
};

struct pinfo {
char * first;
char * last;
int age;
};

int main(void)
{
struct info one = {"Opw", "Cde", 22};
struct pinfo two = {"Tydu", "Gqa", 33};

/* this is ok */
one.first[0] = 'X';

/* this is NOT ok! */
two.first[0] = 'X';

return 0;
}

one contains modifiable arrays. So its ok to modify them.
two points to string constants so it is *not* ok to modify
them. You cannot modify string constants.

This is ok:

int main(void)
{
struct pinfo two;
char first_arr[5] = "Tydu";

two.first = first_arr;
two.first[0] = 'X';

return 0;
}
It's a very simple but clear and helpful example.
I do not understand what you mean when you say "I don't know why it
can not work for the case of two[1], so I want to avoid using char
array. But now, it seems fine.".

Could you give an example which believe may be a problem.

I am thinking about, seems clearly.
 
B

bowlderyu

I see, now.
Thanks.
Happened to me once in the UK, driving on the right side (as opposed to
left, not wrong, but to me that's the same thing :cool:), for several miles on
an empty road in the very early hours of a day. Until a lorry approaching me
on my side stopped me... fortunatly no fatalities, not even a crash.


Some pedestrians were staring at me, but indeed no bobbies in sight...

Bye, Jojo
 
B

bowlderyu

James Kuyper said:
bowlderyu said:
Hello, all.
If a struct contains a character strings, there are two methods to
define the struct, one by character array, another by character pointer.
E.g,
//Program for struct includeing character strings, test1.c

#include <stdio.h>
#define LEN 20

struct info {
char first[LEN];
char last[LEN];
int age;
};

struct pinfo {
char * first;
char * last;
int age;
};

int main(void)
{
struct info one = {"Opw", "Cde", 22};

In this case, you are creating arrays whose contents can be safely
modified, which are stored as part of 'one'.
struct pinfo two = {"Tydu", "Gqa", 33};

In this case, you are creating two unnamed arrays, whose contents
cannot be safely modified. You are storing pointers to those arrays in
two'.
printf("%s %s is %d years old.\n", one.first, one.last, one.age);
printf("%s %s is %d years old.\n", two.first, two.last, two.age);
return 0;
}

//end test1.c

It can work.I know a little,but not very detail that the second struct pinfo is not good

There's no reason why it shouldn't be.
in the above code. E.g, if the struct pinfo two is defined as an array
two[1] in the main function, it can not work. I just want to know the
reason in detail.

If you change how you declare "two":

struct pinfo two[1] = {"Tydu", "Gqa", 33};

Then you also have to change how you use "two":

printf("%s %s is %d years old.\n",
two[0].first, two[0].last, two[0].age);
I regrat that I made a low-level and stupid mistake here,two[1]...
Assuming you made matching changes, as above, there's no reason why it
shouldn't work. Arrays of length 1 are generally pointless, but
they're perfectly legal.


Better in what sense? It's a lot more complicated than either method
you've shown above. I'd use the first method if the strings need to be
writable, but have a small fixed maximum length. I'd use the second
method if the strings don't need to be writable, though I would change
first and last to be "const char*" rather than "char*".
As I mentioned above, I found a method that used malloc() and free()
function for the struct pinfo two. As following

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 20

struct pinfo {
char * first;
char * last;
int age;
};

void setinfo(struct pinfo * ps, char * first, char * last, int age);
void clean(struct pinfo * ps);
int main()
{
char fname[LEN] = "Wqc";
char lname[LEN] = "Oed";
int age = 33;
struct pinfo two;

setinfo(&two,fname,lname,age);
printf("%s %s is %d years old.\n", two.first, two.last, two.age);
//...other operations
clean(&two);
//...other operations
return 0;
}

void setinfo(struct pinfo * ps, char * first, char * last, int age)
{
ps->first = (char *) malloc (strlen(first) + 1);
strcpy(ps->first, first);
ps->last = (char *) malloc (strlen(last) + 1);
strcpy(ps->last, last);
ps->age = age;
}

void clean(struct pinfo * ps)
{
free (ps->first);
free (ps->last);
}

But as you mentioned below, it may be not a better method, even it works
well and seems clearly.
 
N

Nick Keighley

Thank you very much for your work.
And it's a very good suggestion. ....
Ok, the above words are help for me. ....
It's a very simple but clear and helpful example.


perhaps I should frame this sort of stuff
 
J

jameskuyper

bowlderyu said:
James Kuyper said:
bowlderyu wrote: ....
#define LEN 20

struct info {
char first[LEN];
char last[LEN];
int age;
};
.....
As I mentioned above, I found a method that used malloc() and free()
function for the struct pinfo two. As following

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 20

struct pinfo {
char * first;
char * last;
int age;
};

void setinfo(struct pinfo * ps, char * first, char * last, int age);
void clean(struct pinfo * ps);
int main()
{
char fname[LEN] = "Wqc";
char lname[LEN] = "Oed";
int age = 33;
struct pinfo two;

setinfo(&two,fname,lname,age);
printf("%s %s is %d years old.\n", two.first, two.last, two.age);
//...other operations
clean(&two);
//...other operations
return 0;
}

void setinfo(struct pinfo * ps, char * first, char * last, int age)
{
ps->first = (char *) malloc (strlen(first) + 1);

You should always verify whether or not malloc() succeeds. At a
minimum, you need to make sure that you code never attempts to
dereference ps->first, if fs->first is a null pointer, because the
behavior is undefined if it does. Also, since this means that
setinfo() can fail, you should provide some mechanism whereby
setinfo() can report the fact that it failed (giving it a return value
is the method I'd recommend, though there's a lot of other
possibilities). Finally, since setinfo() can fail, you should make
sure that your call to setinfo() from main() checks whether or not it
succeeded.
strcpy(ps->first, first);
ps->last = (char *) malloc (strlen(last) + 1);
strcpy(ps->last, last);
ps->age = age;
}

void clean(struct pinfo * ps)
{
free (ps->first);
free (ps->last);

At this point, ps->first and ps->last have indeterminate pointer
values, and there's no way to even check them because any attempt to
even read those values has undefined behavior. Therefore, I would
strongly recommend setting those pointers to NULL after freeing them.
It's possible to check whether a pointer is NULL, while there's
absolutely no portable way to check whether a pointer points to an
object whose lifetime has expired.

I normally wouldn't bother with that, because I normally make sure
that every pointer to allocated memory has a lifetime that ends right
after the pointer is free()d. However, clean() doesn't have the option
of ensuring that ps->first and ps->second are never used again.
}

But as you mentioned below, it may be not a better method, even it works
well and seems clearly.

Since 'LEN' is 20 in your example, the maximum size is both small and
known, so I would strongly recommend using the approach with fixed-
length arrays, rather than pointers. It will make your code a lot
simpler and more reliable.
 
C

CBFalconer

Joachim said:
.... snip ...

I just don't get Chucks point about "toggle action on the throttle",
probably because I never drove one and only vaguely remember having
seem them (born in '61)

I meant that the only throttle positions I ever observed were
wide-open and shut-down. Well, once in a while we got stuck behind
a truck race up a hill on the autobahn.
 
J

Joachim Schmitz

CBFalconer said:
I meant that the only throttle positions I ever observed were
wide-open and shut-down.

Ah, the 'binary' throttle :cool: (and with that nearing topicality)
Well, once in a while we got stuck behind
a truck race up a hill on the autobahn.

We call'em "elephants' race" over here (truck going 82km/h trying to
overtake another truck, going 81km/h). And they still happen and do cause
major road blocks

Bye, Jojo
 

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

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,058
Members
48,769
Latest member
Clifft

Latest Threads

Top