Query abt union

S

sumit.sharma

Hi,

I have some experience in C prog lang. I have small doubt abt using
unions in C lang.

I have the foll. union

union MyUnion
{
char name [100];
double dblval;
int intVal;
};

Since all the members of union share the same memory space, if we set
the val of one union members, it overwr. the other field's value.
How do the OS maintain that a partic. member is set and not the
other member.

Say like, I use

MyUnion ux;

strncpy(ux.name, "C Language", strlen("C Langage")); /* name is set */

/* try to overwr. name field */

ux.intVal = 0xFF6677;

Now at this time how does OS maintains that intVal is now used... !!!!

Also, if I now try to print name field, what it shld be ??

Pls reply in ur FREE time..there is no urgency..

sumit
 
B

Ben Pfaff

[in a union]
How do the OS maintain that a partic. member is set and not the
other member.

It doesn't. It's the responsibility of the code that uses to
union to keep track of which member has most recently been
assigned.
 
S

Shao Miller

Hi,

I have some experience in C prog lang. I have small doubt abt using
unions in C lang.

I have the foll. union

union MyUnion
{
char name [100];
double dblval;
int intVal;
};

Since all the members of union share the same memory space, if we set
the val of one union members, it overwr. the other field's value.
How do the OS maintain that a partic. member is set and not the
other member.

Say like, I use

MyUnion ux;

I have a doubt about your line, above.

union MyUnion ux;
strncpy(ux.name, "C Language", strlen("C Langage")); /* name is set */

I have a doubt about your line, above.

/* Set the 'name' member */
strncpy(ux.name, "C Language", sizeof ux.name);
/* try to overwr. name field */

ux.intVal = 0xFF6677;

Now at this time how does OS maintains that intVal is now used... !!!!

Already answered by someone else.
Also, if I now try to print name field, what it shld be ??

You should doubt that it will be useful as a "name".
 
J

John Gordon

In said:
strncpy(ux.name, "C Language", strlen("C Langage")); /* name is set */

This seems needlessly complicated. Why wouldn't you just do:

strcpy(ux.name, "C Language")
 
L

Lew Pitcher

On June 23, 2011 16:07, in comp.lang.c, (e-mail address removed) wrote:

[snip]
union MyUnion
{
char name [100];
double dblval;
int intVal;
};
[snip]
MyUnion ux;

strncpy(ux.name, "C Language", strlen("C Langage")); /* name is set */

As an aside, the above illustrates a common problem found when programmers
overuse string literals. Here, the strncpy() will result in ux.name being
set to the string array "C Languag", dropping the final "e"

Do you see why? Hint: it has to do with the string literals.


[snip]
 
S

Shao Miller

On June 23, 2011 16:07, in comp.lang.c, (e-mail address removed) wrote:

[snip]
union MyUnion
{
char name [100];
double dblval;
int intVal;
};
[snip]
MyUnion ux;

strncpy(ux.name, "C Language", strlen("C Langage")); /* name is set */

As an aside, the above illustrates a common problem found when programmers
overuse string literals. Here, the strncpy() will result in ux.name being
set to the string array "C Languag", dropping the final "e"

Do you see why? Hint: it has to do with the string literals.


[snip]

It also doesn't copy the null terminator, if I'm not mistaken. Since
'ux.name' has a limit, I think using that limit makes some sense.
 
J

Joe Pfeiffer

Lew Pitcher said:
On June 23, 2011 16:07, in comp.lang.c, (e-mail address removed) wrote:

[snip]
union MyUnion
{
char name [100];
double dblval;
int intVal;
};
[snip]
MyUnion ux;

strncpy(ux.name, "C Language", strlen("C Langage")); /* name is set */

As an aside, the above illustrates a common problem found when programmers
overuse string literals. Here, the strncpy() will result in ux.name being
set to the string array "C Languag", dropping the final "e"

Do you see why? Hint: it has to do with the string literals.

Ah, I didn't see that one (requires very careful reading!). I was about
to post another, worse bug in the same line: it guarantees no trailing
null at the end of the string (we just had a brief discussion of
strncpy()'s problem in this regard!). Better would be

strncpy(ux.name, "C Language", sizeof(ux.name));
ux.name[sizeof(ux.name)-1] = '\0';

Though this is, of course, inefficient.

Somebody else suggested using strcpy(); since the string being copied is
a literal a good code review will would then establish no buffer
overrun.
 
K

Keith Thompson

Shao Miller said:
On June 23, 2011 16:07, in comp.lang.c, (e-mail address removed) wrote:

[snip]
union MyUnion
{
char name [100];
double dblval;
int intVal;
};
[snip]
MyUnion ux;

strncpy(ux.name, "C Language", strlen("C Langage")); /* name is set */

As an aside, the above illustrates a common problem found when programmers
overuse string literals. Here, the strncpy() will result in ux.name being
set to the string array "C Languag", dropping the final "e"

Do you see why? Hint: it has to do with the string literals.
[snip]

It also doesn't copy the null terminator, if I'm not mistaken. Since
'ux.name' has a limit, I think using that limit makes some sense.

But since strncpy() pads the destination with nulls, ux.name ends up
containing a valid string (and 91 nulls where 1 would do).

General rule: Don't use strncpy unless you really understand what it
does. (And if you understand what it does, you probably won't want to
use it.)
 
J

Joe Pfeiffer

Keith Thompson said:
But since strncpy() pads the destination with nulls, ux.name ends up
containing a valid string (and 91 nulls where 1 would do).

General rule: Don't use strncpy unless you really understand what it
does. (And if you understand what it does, you probably won't want to
use it.)

It really is too bad there isn't a good library function to copy a
string safely -- building one on top of memcpy() or even doing it by
hand is easy, but it would be better if it were in the library.

Is the implementation of snprintf() typically efficient enough to make
sense for this purpose?
 
K

Keith Thompson

Joe Pfeiffer said:
It really is too bad there isn't a good library function to copy a
string safely -- building one on top of memcpy() or even doing it by
hand is easy, but it would be better if it were in the library.

Something like this is pretty close:

#define STRNCPY(dest, src, n) \
(*(dest) = '\0', strncat((dest), (src), (n)))

It evaluates dest twice, but that shouldn't be a problem.

[...]
 
J

Joe Pfeiffer

Keith Thompson said:
Something like this is pretty close:

#define STRNCPY(dest, src, n) \
(*(dest) = '\0', strncat((dest), (src), (n)))

It evaluates dest twice, but that shouldn't be a problem.

Ah, nice. I'll have to remember that...
 
B

Ben Bacarisse

Joe Pfeiffer said:
Ah, nice. I'll have to remember that...

I slightly prefer

#define STRNCPY(dest, src, n) strncat(strcpy((dest), ""), (src), (n))

because it does not evaluate dest twice though, as Keith says, that's
not likely to be a problem. Beware, also, of the meaning of n -- you
can't use the size of the destination array since a null character is
added (i.e. n + 1 bytes are written to dest). You might consider:

#define STRNCPY(dest, src, n) \
(n ? strncat(strcpy((dest), ""), (src), (n) - 1) : dest)

if you feel that's more natural. It probably depends on how STRNCPY
will be used. The C library is inconsistent in this regard, but newer
function like snprintf take a size that limits what is written, not how
many non-null characters are written.

<OT>
If C's assignments were like C++'s then once could write:

#define STRNCPY(dest, src, n) strncat(&(*(dest) = '\0'), (src), (n))

and avoid the extra call.
</OT>
 
J

James Waldby

Note to OP -- For proper English usage, write 'question' rather
than 'doubt' in the above. Also, avoid glaringly stupid abbreviations
like abt, foll., overwr., partic., and shld. (Non-glaring stupid
abbreviations like prog lang and val perhaps are ok.)
I have the foll. union

union MyUnion
{
char name [100];
double dblval;
int intVal;
};

Since all the members of union share the same memory space, if we set
the val of one union members, it overwr. the other field's value. How
do the OS maintain that a partic. member is set and not the other
member. ....
MyUnion ux;
I have a doubt about your line, above.

union MyUnion ux;
strncpy(ux.name, "C Language", strlen("C Langage")); /* ... */
I have a doubt about your line, above.

/* Set the 'name' member */
strncpy(ux.name, "C Language", sizeof ux.name);
....

On the one hand, the line you are correcting doesn't work [copies
"C Languag", not "C Language", into ux.name, and fails to terminate
string with nil]; on the other, your correction works inefficiently
as it writes 89 superfluous nil's into ux.name. I think a temperate
programmer would instead write
strcpy(ux.name, "C Language");
or
union MyUnion ux = {.name="C Language"};
or without '.name=', as in following code:

#include <stdio.h>
union MyUnion {
char name [100]; double dblval; int intVal; };

int main(void) {
union MyUnion ux = {"C Language"};
printf ("%s\n", ux.name);
ux.name[2] = 'l';
printf ("%s\n", ux.name);
ux.intVal += 32-(32<<16); /* not recommended */
printf ("%s\n", ux.name);
return 0;
}

On x86 linux/gcc systems and perhaps other x86 systems this outputs:
C Language
C language
c Language
 
S

Shao Miller

Note to OP -- For proper English usage, write 'question' rather
than 'doubt' in the above.

I expect another "doubt" before the end of the day.
I have the foll. union

union MyUnion
{
char name [100];
double dblval;
int intVal;
};

Since all the members of union share the same memory space, if we set
the val of one union members, it overwr. the other field's value. How
do the OS maintain that a partic. member is set and not the other
member. ...
MyUnion ux;
I have a doubt about your line, above.

union MyUnion ux;
strncpy(ux.name, "C Language", strlen("C Langage")); /* ... */
I have a doubt about your line, above.

/* Set the 'name' member */
strncpy(ux.name, "C Language", sizeof ux.name);
...

On the one hand, the line you are correcting

"Suggesting," I'd say. The original intention is actually uncertain.
doesn't work [copies
"C Languag", not "C Language", into ux.name, and fails to terminate
string with nil]; on the other, your correction works inefficiently
as it writes 89 superfluous nil's into ux.name.

The line of code under discussion leaves _much_ to be desired, in my
opinion.

- Using 'strlen' on a string literal seems silly when one can use 'sizeof'.

- The string literal for 'strlen' is a character short due to
[presumably] a typographical error.

- _Without_ the typo., 'strlen' is going to yield a number of characters
that prevents the null character from being copied into the 'ux.name'
array. 'ux.name' will then not necessarily contain a string.

- Using any length related to the string literal for 'strncpy' is silly;
the limit ought to be related to the destination array, instead.

The line of code thus strikes me as... Suspicious. Suppose it's sincere:

Why did the original poster use 'strncpy', do you suppose? Did they
want some kind of safety? If so, what could be safer than the suggested:

strncpy(ux.name, "C Language", sizeof ux.name);

? Maybe following it with:

ux.name[sizeof ux.name - 1] = '\0';

?

The "inefficient" population of redundant null characters can be viewed
as a "safety" feature. Whatever garbage is there is cleared.
I think a temperate
programmer would instead write
strcpy(ux.name, "C Language");
or
union MyUnion ux = {.name="C Language"};
or without '.name=', as in following code:

#include<stdio.h>
union MyUnion {
char name [100]; double dblval; int intVal; };

int main(void) {
union MyUnion ux = {"C Language"};

Please tell me about the difference in behaviour (in regards to
"efficiency," perhaps) between this initialization and the example
'strncpy' line I gave above as a suggestion to the original post.
[...more code...]

Not that we'll ever read from this original poster again, like so many
others (and who might all be the very same, doubt-wielding poster).
 
J

James Waldby

On 6/23/2011 3:07 PM, sumit.sharma wrote:
[snip]
union MyUnion ux;

strncpy(ux.name, "C Language", strlen("C Langage")); /* ... */

I have a doubt about your line, above.

/* Set the 'name' member */
strncpy(ux.name, "C Language", sizeof ux.name);
...
On the one hand, the line you are correcting

"Suggesting," I'd say. The original intention is actually uncertain.
True!
doesn't work [copies "C Languag", not "C Language", into
ux.name, and fails to terminate string with nil]; on the
other, your correction works inefficiently as it writes 89
superfluous nil's into ux.name.

The line of code under discussion leaves _much_ to be desired, in my
opinion.

- Using 'strlen' on a string literal seems silly when one can use
'sizeof'.

- The string literal for 'strlen' is a character short due to
[presumably] a typographical error.

- _Without_ the typo., 'strlen' is going to yield a number of characters
that prevents the null character from being copied into the 'ux.name'
array. 'ux.name' will then not necessarily contain a string.

- Using any length related to the string literal for 'strncpy' is silly;
the limit ought to be related to the destination array, instead.

The line of code thus strikes me as... Suspicious. Suppose it's
sincere:

Why did the original poster use 'strncpy', do you suppose? Did they
want some kind of safety?

I imagine OP used strncpy() due to ignorance of alternatives, or
perhaps because of exposure to bad examples. In light of the
problems that you list above, a 'safety' rationale seems unlikely.
If so, what could be safer than the suggested:

strncpy(ux.name, "C Language", sizeof ux.name);

? Maybe following it with:

ux.name[sizeof ux.name - 1] = '\0';
? ....
I think a temperate
programmer would instead write
strcpy(ux.name, "C Language");
or
union MyUnion ux = {.name="C Language"};
or without '.name=', as in following code:

#include<stdio.h>
union MyUnion {
char name [100]; double dblval; int intVal; };

int main(void) {
union MyUnion ux = {"C Language"};

Please tell me about the difference in behaviour (in regards to
"efficiency," perhaps) between this initialization and the example
'strncpy' line I gave above as a suggestion to the original post.

In comparing
union MyUnion ux = {"C Language"};
to separate declaration and initialization of ux, I see
efficiency as of far less importance than correctness, clarity,
and brevity, on which counts the combined statement excels. Of
course the combined statement *is* far more efficient, probably
saving over 10ns of runtime per program execution relative to
initialization by strcpy(), and probably over 50ns relative to
strncpy(), and saving easily a handful of bytes in program size.
 
J

John Gordon

In said:
char mystring[10];
void mystrcpy(const char *arg) {
strncpy(mystring, arg, sizeof(mystring) - 1);
mystring[sizeof(mystring) - 1] = '\0';
}

A quibble with this particular implementation: Your wrapper function uses
sizeof to get the size of the destination buffer, which a general-purpose
function wouldn't be able to do.
 
K

Keith Thompson

pozz said:
Il 24/06/2011 02:19, Keith Thompson ha scritto:
General rule: Don't use strncpy unless you really understand what it
does. (And if you understand what it does, you probably won't want to
use it.)

Sorry, but I'm not able to follow your discussion. Why should I avoid
strncpy()?

I have a string buffer defined with a fixed dimension:
char mystring[10];

Now I have to copy an unknown string, maybe passed in as an argument
function, to mystring array. If I use strcpy(), I could write memory
after mystring[].

So I think strncpy() is good to avoid this bad situations:

char mystring[10];
void mystrcpy(const char *arg) {
strncpy(mystring, arg, sizeof(mystring) - 1);
mystring[sizeof(mystring) - 1] = '\0';
}

What is wrong with this?

strncat() is a safer version of strcat(); it takes an extra argument,
n, that specifies the maximum number of characters to copy.
It guarantees that, unless you go past the bounds of the source
or the destination, the destination will contain a valid (i.e.,
null-terminated) string.

strncpy(), in spite of the misleading name, is *not* a safer version
of strcpy(). strncpy() can easily leave the destination array in
a state where it doesn't contain a valid string. If n is much
larger than the size of the source, it will pad the destination
with multiple null characters, which is usually not useful.

A function that is to strcpy() as strncat() is to strcat() would
be useful, and strncpy() would have been a good name for it.
But there is no such function in the standard library (thought it's
easy enough to roll your own), and the name strncpy() is already
taken for this bizarre thing.
 
E

Edward Rutherford

Keith said:
A function that is to strcpy() as strncat() is to strcat() would be
useful, and strncpy() would have been a good name for it. But there is
no such function in the standard library (thought it's easy enough to
roll your own), and the name strncpy() is already taken for this bizarre
thing.

I think the function you're looking for is strlcpy(), present in most
modern C distributions but easy enough to write oneself should it be
absent. It helpfully returns the length of the source string, so you can
use constructions like

if(strlcpy(buf, src, sizeof buf) >= sizeof buf) {
/* truncation happened */
}

//EPR
 
J

Joe Pfeiffer

pete said:
C is not all about
being able to write good programs
without paying attention to what you're doing.

It's not difficult to copy a string safely with strcpy.

Sure -- it's just that it's even easier to do it unsafely. You can do a
lot to force programmers to write safe code by banning sprintf(),
gets(), strcat(), and the like; you can't get the same effect by banning
strcpy().
 
K

Keith Thompson

Edward Rutherford said:
I think the function you're looking for is strlcpy(), present in most
modern C distributions but easy enough to write oneself should it be
absent. It helpfully returns the length of the source string, so you can
use constructions like

if(strlcpy(buf, src, sizeof buf) >= sizeof buf) {
/* truncation happened */
}

It's not necessarily what I'm looking for. What I really had in mind
for what strncpy() *should* have been is a function that's to strcpy()
exactly as strncat() is to strcat().

(Note that strlcpy() may well be *better* than any of strcpy(),
strncpy(), or what-strncpy-should-have-been().)
 

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
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top