Tony said:
I'm just learning C as another language, and I'm trying to build some
utilities into a library. I have this (crude I know) function:
void insert(char* insrt, char* source, int place){
char temp[strlen(insrt)+strlen(source)+1];
Your compiler lets you declare that? Is this some new C99 feature? I
think gcc lets you do things like this, but I don't think its ISO C89
compliant. Basically, declaration sizes have to be compile-time
constants, in most C compilers out there. So something like:
char * temp = (char *) malloc(1+strlen (instr)+strlen (source));
if (temp) {
/* Do inner loop */
free (temp);
}
is more portable and more compliant.
strncpy(temp, source, place);
temp[place]='\0';
strcat(temp, insrt);
strcat(temp, source+place);
strcpy(source, temp);
}
Ok, you are modifying the source, but not the insrt string. I would
therefore highly recommend that you declare the function as follows:
void insert (const char* insrt, /*@out@*/char* source, int place) {
The const tells us that the object its point to will not be modified.
The /*@out@*/ declares to tools like SPLINT that the destination can be
modified by the call (personally, I don't know why SPLINT doesn't just
assume that that will happen).
As a matter of performance, I would just like to point out that you
don't need to perform any work on the characters from 0 up to but
excluding place. In other words:
strcpy (temp, insrt);
strcat (temp, source+place);
strcpy (source+place, temp);
Works just as well, without redundantly copying over the first place
characters. You could do even better if C had some sort of "copy and
give me the length" function, but it doesn't.
In a simple file, it all works, but in a static library, when I call it I
get a segnmentation fault. The villain is the final strcpy.
That's because inline strings are not modifiable -- though no C
compiler that I know of does any compile time checking of this fact for
you. I.e.,
char * s;
insert ("Constant string ", s = "Unwritable string", 11);
is wrong because "Unwritable string" cannot be modified. Changing this
to:
char s[128 /* MAGIC CONSTANT */] = "Writable string";
insert ("Constant string ", s, 9);
And the program will work once again.
I tried returning temp instead and that doesn't work either, I don't get
quite the string that exists in the function (and the compiler warns about
returning a local variable).
The storage for temp is only defined for the scope of the insert()
function. I.e., literally the part of the call stack that is used to
execute insert() disappears once it returns, and that includes the
storage for the locally scoped variables in that function.
I know there's a solution, I just have no idea what it is. Any help would
be great.
Download the Better String Library here
http://bstring.sf.net
Then do the following:
#include <strdio.h>
#include "bstrlib.h"
/* ... */
bstring s;
struct tagbstring i = bsStatic ("better ");
binsert (s = bfromcstr ("a string library"), &i, 2, '?');
puts (bdatae (s, "Out of memory"));
bdestroy (s);