why this code does not compile?

N

Ninan Thomas

#define MAX_PATH_NAME 100


char audithome[MAX_PATH_NAME];

audithome = getenv("AUDITHOME");



this fails to compile giving an error
"incompatible types in assignment"

I am using gcc compiler on Solaris

REgards

Ninan
 
M

Martin Dickopp

Allan Bruce said:
Ninan Thomas said:
#define MAX_PATH_NAME 100


char audithome[MAX_PATH_NAME];

audithome = getenv("AUDITHOME");



this fails to compile giving an error
"incompatible types in assignment"

I am using gcc compiler on Solaris

REgards

Ninan

getenv returns a char pointer, so you should have something like


#define MAX_PATH_NAME 100

char *audithome = malloc(MAX_PATH_NAME);

audithome = getenv("AUDITHOME");

No! That would be a memory leak. After the `getenv' call, there's no
way to access the memory returned by the `malloc' call.

To the OP: It doesn't work because you cannot assign to an array.
`getenv' returns a pointer to char, so the correct way to call it is:

char *audithome = getenv("AUDITHOME");

Note that `getenv' can return a null pointer. If it doesn't, the memory
pointed to by `audithome' should not be modified. Furthermore, future calls
to `getenv' may overwrite the same memory.

Martin
 
A

ataru

Martin Dickopp said:
char *audithome = getenv("AUDITHOME");

So maybe

char audithome[MAX_PATH];
strncpy(audithome, getenv("AUDITHOME"), MAX_PATH - 1);

? (emphasis on '?', allowing for the coefficient of stupidity to kick in...)
 
M

Mike Wahler

Ninan Thomas said:
#define MAX_PATH_NAME 100


char audithome[MAX_PATH_NAME];

audithome = getenv("AUDITHOME");

Note that 'getenv()' is not a standard C function.
But that's not the essence of the problem.
this fails to compile giving an error
"incompatible types in assignment"

Right. And in this case there is *no* 'compatible type'.
IMO that message is misleading. It's not allowed to
assign to an array.

What type does that function 'getenv()' return?
If it returns a pointer to a char, then use 'strcpy()'
to write to the array (or perhaps simply assign the
return value to a char*.) You should check the documentation
to see if it might return NULL, in which case you don't
want to dereference the returned value. Also, if using a
'C89' compiler', and you don't provide a prototype, its
return type will be assumed to be 'int'. If using a 'C99'
compiler, calling a function whose prototype is not in scope is
not allowed.

-Mike
 
M

Martin Dickopp

Martin Dickopp said:
char *audithome = getenv("AUDITHOME");

So maybe

char audithome[MAX_PATH];
strncpy(audithome, getenv("AUDITHOME"), MAX_PATH - 1);

This fails (causes undefined behavior) if `getenv' returns a null pointer.
Furthermore, `strncpy' does not write a '\0' character if its second
argument is a string of the length indicated by the third argument or
longer.

char *const tmp = getenv ("AUDITHOME");
if (tmp != 0)
{
char audithome [MAX_PATH];
strncpy (audithome, tmp, sizeof audithome - 1);
audithome [sizeof audithome - 1] = '\0';
/* ... */
}

Martin
 
A

ataru

Martin Dickopp said:
Furthermore, `strncpy' does not write a '\0' character if its second
argument is a string of the length indicated by the third argument or
longer.

You know, I didn't believe you until I saw it in the man page myself... Why
doesn't it?
 
A

ataru

Ben Pfaff said:
* Using strncpy() into a large buffer can be very inefficient.
strncpy() always writes to every byte in the destination
buffer, which can waste a lot of time if the destination
buffer is much longer than the source string.

Why is it implemented like this, if there is such a large performance penalty
for writing to every byte?
 
C

CBFalconer

Ninan said:
#define MAX_PATH_NAME 100

char audithome[MAX_PATH_NAME];

audithome = getenv("AUDITHOME");
^^^^^^^^^ ^---------see below for what this returns.
this is not an lvalue.
this fails to compile giving an error
"incompatible types in assignment"

I am using gcc compiler on Solaris

Which has nothing to do with it. From N869:

7.20.4.4 The getenv function

Synopsis
[#1]
#include <stdlib.h>
char *getenv(const char *name);

Description

[#2] The getenv function searches an environment list,
provided by the host environment, for a string that matches
the string pointed to by name. The set of environment names
and the method for altering the environment list are
implementation-defined.

[#3] The implementation shall behave as if no library
function calls the getenv function.

Returns

[#4] The getenv function returns a pointer to a string
associated with the matched list member. The string pointed
to shall not be modified by the program, but may be
overwritten by a subsequent call to the getenv function. If
the specified name cannot be found, a null pointer is
returned.
 
S

Simon Biber

You know, I didn't believe you until I saw it in the man page
myself... Why doesn't it?

Despite its name, strncpy is not designed to produce strings, but
rather to produce fixed width records, arrays of characters, in
which the absence of a null character simply means that all
available characters are used. This avoids wasting space for a
redundant null character when the fixed width of the record is
well-known.

An example is the directory file format on some older operating
systems, which has a fixed width record holding (say) 11 characters:
A B C D E F G H J K L
if all are filled, this represents the filename "ABCDEFGH.JKL".
if not all are filled:
A B C D E F \0 \0 D O C
this represents "ABCDEF.DOC"
H E L L O \0 \0 \0 C \0 \0
this represents "HELLO.C"

One way to fill such a record is with strncpy:

char buf[11] = {0};
strncpy(buf, "HELLO", 8);
strncpy(buf + 8, "C", 3);

This way you can use the whole 8+3 space for the filename without
wasting space storing the dot or null terminators.

On modern systems which support very long filenames, it is
space-inefficient to use a fixed record width, which would
waste much space storing zeroes for shorter filenames, so new
variable length schemes have been introduced. However, fixed
width records still exist and are quite useful in other areas.
 
S

Simon Biber

CBFalconer said:
Ninan said:
#define MAX_PATH_NAME 100

char audithome[MAX_PATH_NAME];

audithome = getenv("AUDITHOME");
^^^^^^^^^ ^---------see below for what this returns.
this is not an lvalue.

It is an lvalue. It is not a modifiable lvalue.

C99 6.3.2.1 Lvalues, arrays, and function designators
1 An lvalue is an expression with an object type or an
incomplete type other than void;53) if an lvalue does
not designate an object when it is evaluated, the
behavior is undefined. When an object is said to have
a particular type, the type is specified by the lvalue
used to designate the object. A modifiable lvalue is
an lvalue that does not have array type, does not have
an incomplete type, does not have a const-qualified
type, and if it is a structure or union, does not have
any member (including, recursively, any member or
element of all contained aggregates or unions) with a
const-qualified type.
 
N

Ninan Thomas

Hi all
Thanks for all the replies to this question. I have a follow up question.

I agree
char *audithome = getenv("AUDITHOME");
works.

My question is if i define

char audithome[MAX_PATH_NAME];

and pass it as an argument to any function for example
strcpy (char *, ------

strcpy(audithome,
it works. Here the argument is a pointer to char type???
where as it does not work when the function returns a char * type?

for example char *getenv(-------


audithome = getenv("AUDITHOME")
 

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
473,774
Messages
2,569,596
Members
45,141
Latest member
BlissKeto
Top