-3

I'm trying to write my own version of strcat (I call it "append"). Here's what I have:

#include <stdio.h>

int main() {

  char *start = "start";
  char *add = "add";
  append(start, add);
  printf(start);

}

void append(char *start, char *add) {
  //get to end of start word
  char *temp = &start;
  while (*temp != '\0') {
    temp++;
  }
  *temp = *add;
  while (*temp != '\0') {
     *temp = *add; 
  }
}

When I compile, I get 3 warnings and an error:

1) warning: implicit declaration of function 'append' is invalid in C99

2) warning: format string is not a string literal (potentially insecure)

3) error: conflicting types for 'append'

I don't see how the arguments I pass into my append function within main conflict with the function definition below it.

4) warning: incompatible pointer types initializing 'char *' with an expression of type 'char **'; remove &

Why would I want to remove & here? I thought I could declare and initialize my char pointer to the proper memory address all at once.

Any help is much appreciated.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
anon_swe
  • 8,791
  • 24
  • 85
  • 145
  • 3
    [You need this badly](http://stackoverflow.com/q/562303/2455888). – haccks Apr 24 '15 at 20:50
  • You can't do that. For one thing, the string literals could be in read-only memory. For another, there won't be any spare memory in `start` to append `add`. More - `char *temp = &start;` should be `char *temp = start;` since you have been passed a pointer. – Weather Vane Apr 24 '15 at 20:52
  • 1
    @haccks Sir, you beat [my 26 line answer](http://stackoverflow.com/a/29857229/2173917) by [just 1 line](http://stackoverflow.com/questions/29857186/c-compilation-error-for-basic-function#comment47840310_29857186). :-) – Sourav Ghosh Apr 24 '15 at 21:25

4 Answers4

3

1) warning: implicit declaration of function 'append' is invalid in C99

and

3) error: conflicting types for 'append'

because, you did not provide a prototype of append() before using it. You need to add a forward declaration of a function before using it. Add

void append(char *start, char *add);

before main() or put the function definition before main()

Next, in case of

 char *start = "start";
 char *add = "add";

start and add are the pointers to string literals. They are usually placed in read-only memory, means you cannot change the contents. Any attempt to do so will lead to undefined behavior.

Then, regarding

2) warning: format string is not a string literal (potentially insecure)

printf(start);

is wrong usage in this case. You need to use it like

printf("%s\n", start);

Check the man page of printf() for more details.

and finally,

4) warning: incompatible pointer types initializing 'char *' with an expression of type 'char **'; remove &

is because of

char *temp = &start;

you need to use something like

char *temp = start;   //start is a char *, no need for & here

Note: The recommended signature of main() is int main(void).

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
2

You have multiple problems with that short code. First you have

warning: implicit declaration of function 'append' is invalid in C99

The meaning of this warning is that you need to declare functions before you use them. If you don't declare a function before you use it, the compiler will have to guess its arguments and return type, and often it guesses badly.

Continuing with next warning:

warning: format string is not a string literal (potentially insecure)

This is because you provide a string variable to printf, this is, like the warning tells you, insecure. Think for example about a case where you read input from a user, and use that input as a format string to printf. What would stop the user from adding format codes in the input string? And since you don't pass arguments where would the arguments for those formats come from?

And now the error:

error: conflicting types for 'append'

This is because of the first problem, that the compiler guessed the arguments or return type of the function wrongly.


Now on to another major problem that doesn't show up as compiler errors or warnings, namely undefined behavior.

The problem is that your start and add variables points to string literals. String literal are read only (in fact, a string literal is a pointer to an array of non-modifiable characters). The first problem is that you try to modify the contents of these arrays, the second is that the arrays are only as big as needed and you are writing outside of that memory. Both these problems are causes for undefined behavior.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Note: I thought it was undefined behavior what happens when code attempts to modify a string literal? It isn't that string literals are read only - they could be read only - they might not. Certainly agree code should not attempt to modify them. – chux - Reinstate Monica Apr 24 '15 at 21:07
  • @JoachimPileborg So even if I had an array of chars that was large enough, I can't modify it. So how would a C person write an append function. Just create a whole new (larger) array of characters within the method and copy in the start array of chars, add the add array of chars, then return this newly created array of chars? – anon_swe Apr 26 '15 at 01:44
  • @bclayman If you have an *array* you can modify it, like e.g. `char start[256] = "start";` – Some programmer dude Apr 26 '15 at 09:38
2

But this is the easy part, what the compiler could detect.

The worse part is that as you declared start as char *start = "start", it only points to an array of 6 chars (5 letters + terminating null).

So when you try to add add at its end you get Undefined Behaviour (for writing beyond and of an array) ! In that case you are writing memory where any else could be => your program is likely to break or segfault.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
1

C99 is pretty restrictive in how it wants you to declare things.

As Sourav said, 1 & 3 are caused by your append() function is used before it's declared in the file, which causes the compiler to generate an implicit declaration for you. Move the append() function above main() to fix that (or add a function prototype).

4 is caused by this line: char *temp = &start;

temp here is actually a char**, since you're taking the address of a char*