On Wed, 2 Jun 2004 17:20:49 GMT, "Joe Laughlin"
<Jo************ ***@boeing.com> wrote in comp.lang.c:
Jack Klein wrote: On Wed, 2 Jun 2004 00:48:45 GMT, "Joe Laughlin"
<Jo************ ***@boeing.com> wrote in comp.lang.c:
#include <stdio.h>
#include <string.h>
Need to add:
#include <stdlib.h>
Noted.
...here to have a proper prototype for malloc() in scope.
[snip]
char *path = (char*)malloc(B UF_LENGTH);
Never cast the return value of malloc() in C. If you did
this to shut up compiler warnings, we fixed that properly
by including <stdlib.h> for malloc's prototype. Without
that prototype, the cast eliminates the warning but
specifically does the wrong thing on some platforms.
Why shouldn't I cast the return value of malloc()?
Casting the return value of malloc() is:
1. Not necessary in C as the memory allocation functions (malloc,
calloc, and realloc) all return a pointer to void. In C, a pointer to
void may be assigned to a pointer to any object type directly, with no
cast.
2. Prevents a required diagnostic if a proper prototype for malloc is
not in scope, as in this case where <stdlib.h> was not included.
Prototypes, or at least declarations, for all functions are required
in the latest (1999) version of the C standard, but most compilers
today still operate according to an earlier standard version. Without
a declaration, the compiler must assume that the function returns an
int and accepts whatever arguments (after default promotions) that you
pass to it. Without the cast the compiler is required to issue a
diagnostic because assigning the assumed int returned by malloc to a
pointer without a cast is a constraint violation, thus warning you
that you have missed something.
3. By preventing the diagnostic that would cause you to fix the
problem properly (by including <stdlib.h>), this can cause some very
nasty errors. There are some platforms where pointers and ints are
returned differently, for example in different processor registers.
And there are 64-bit platforms today, and more of them all the time,
where int and pointers are different sizes, 32 bits for int and 64
bits for pointers.
With the prototype and without the cast, the compiler will happily
take the irrelevant value in the integer return register, convert it
to a pointer, and store that, completely ignoring the real pointer
value in the proper register. Or if ints and pointers are returned in
the same way, it will happily throw away the top 32 bits of the real
64-bit pointer, then zero extend or sign extend the lower 32 bits into
64. The most likely result is a seg fault when the pointer is
dereferenced.
There have been a large number of platforms at various times where int
and pointer happened to have the same size. This was very common in
the early days of 8 and 16-bit processors, and on today's 32-bit
desktops (Windows, *NIX, etc.). The majority of these platforms also
happen to return ints and pointers in the same register, so this sort
of sloppy programming "works by accident" a large part of the time on
many platforms. But it has never been correct C, and there have
always been platforms where it doesn't work. With the ongoing
transition from 32 to 64 bits on the desktop, there will be a lot more
platforms in the future where it doesn't work by accident.
memset(path, 0, BUF_LENGTH);
First, you don't need to set the entire buffer to 0 for
what you are doing. Second, if you do need to allocate
memory for an array of characters and have it all zeroed,
calloc() will do both operations in one call. Note that
calloc() is guaranteed to initialize an array of
characters to all valid '\0' values, it is not so
guaranteed to do so with any other type.
calloc()? I tried 'man calloc' on my linux system, but it didn't find the
man page.
Then your man pages are deficient. The calloc() function has part of
the C library since before the original K&R boot (1978) and part of
every C standard since the original 1989 ANSI version. Get a better
reference.
But all you really need is one '\0' at the beginning, so
you could just code:
*path = '\0';
/* The length of the file path should be the
difference between the * location of file pointer
and the string pointer. I can't always assume
* this, right? */
int length_of_file_ path = file_name - string;
The length of the string prior to the final '/',
excluding the final '/' but allowing for a '\0' in its
place to terminate it, is exactly file_name - string. It
can't ever be anything else (if strrchr() does not return
NULL). You can always assume this.
Ok. I was wondering what would happen if the character array was not stored
in one contigous block in memory (i.e. if it were really long). The
subtracting the two addresses of the pointers would not give me the correct
length.
No matter how long they are, if they exist they are contiguous.
Arrays are always contiguous, as are the bytes allocated by malloc,
calloc, or realloc. Your operating system might provide virtual
memory, so they might be scattered all over physical memory or even
partially in a swap file, but that is all transparent to a C program.
To the program they are always contiguous and always will be.
/* Put the first length_of_file_ path characters into
path */ strncat(path, string, length_of_file_ path);
The problem with this is length_of_file_ path includes the
final '/', which you do not want to appear in the path
string (or do you?). If you don't, use
length_of_file_ path - 1 as the length argument.
I did want the final '/' to be included.
OK, but that is not how your original post read.
printf("The file path is %s\n", path);
}
Thanks for your help!
You're welcome.
--
Jack Klein
Home:
http://JK-Technology.Com
FAQs for
comp.lang.c
http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++
http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html