Solved

String Handling in "C"

Posted on 2002-03-13
21
292 Views
Last Modified: 2010-04-15
Hello

# include<stdio.h>
# include<string.h>

int main (void)
{
     char str[9] = "hello";
     char str1[]=  "world";
     
     strcat(str, str1);
     printf("%s", str);
}

I expected the above program to give "Application Error"
since str can hold only 9 characters, but we try to
have 10 chars (helloworld) after doing strcat. But to
my surprise the program ran successfully without any error. I used Microsoft visual c++  on win NT to test
this. Can you explain why it didn't give error?


b)Is it possible to use strcat for a variable that is
declared as char *x="test" using pointers (or)
is strcat always used with array of characters declared using [] rather than character pointer.


Thanks
Sridhar
0
Comment
Question by:puji
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 6
  • 4
  • +3
21 Comments
 
LVL 4

Expert Comment

by:newmang
ID: 6862854
Sridhar

This behaviour is one of the downsides of the freedoms provided by C. There is no concept of length checking so when you did your strcat the data in str1 would have been copied into the memory area allocated to str and would have written past the end of the area allocated into str, in the process overwriting whatever happened to be there.

The printf worked because a string is an array of characters terminated by a null (0x00). You were lucky in this case because there was obviously nothing of consequence in the memory area following str but if there had been significant information there then you r program may have crashed or exhibited odd behaviour.

This is a frequent cause of strange behaviour in programs as a strcat at one place in the application may over-write a variable used somewhere else in the program. It is also a classic cause of program cracking and is very dangerous.

You really should use the strncat() function where you define both the source string, the destination string and the number of characters to copy - strncat(source, dest, sizeof(dest)-1) to avoid this problem.

The answer to b) is yes. In fact when you typed strcat(str, str1) you were passing to the strcat function the address of str and the address of str1 which is what iy would do if you used explicit pointers. So the following are valid.

char str[10]="xxxx";
char str1[10]="yyyy"
strncat(str,str1,9);

char str[10]="xxxx";
char str1[10]="yyyy"
strncat(&str[0], &str1[0],9);

char * pstr;
char * pstr1;
pstr=(char *)malloc(10);
pstr=(char *)malloc(10);
strcpy(pstr,"xxxx");
strcpy(pstr1,"yyyy");
strncpy(pstr,pstr1,9);
.
.
free(pstr);
free(pstr1);

I hope this helps - Gavin Newman
0
 
LVL 5

Expert Comment

by:nebeker
ID: 6863770
One of the reasons it worked is because when you allocated the 9 characters for the 'str[9]', you really got more than 9 characters :)

Behind the scenes, the memory manager that handles malloc and the list of free pages generally trys to return memory on even 4 byte (or multiples of 4 byte) boundaries.

For example, consider this simple program:
---------------------------------------------------------

#include <stdio.h>

int main( void )
{
    char *p1 = (char *) malloc( 1 );
    char *p2 = (char *) malloc( 1 );

    printf( "p1 = %p, p2 = %p\n", p1, p2 );
    return 0;
}
---------------------------------------------------------

At first glance, you might think that the memory allocated for pointer "p2" is going to be 1 byte after pointer "p1".  But when I ran this program, I got the following output:

p1 = 0xa010320, p2 = 0xa010330

which shows a difference of 0x10, which tells me that malloc is aligning things on a 16 byte boundary.  This means that I could write an extra 15 bytes to pointer "p1" and not blow up my program.

Of course, you can't always rely on this, since you have no idea where the boundaries will be....
0
 
LVL 12

Expert Comment

by:pjknibbs
ID: 6863961
nebeker: However, malloc() has nothing to do with this situation because malloc() is not used to allocate memory for a declaration like char str[9]. In this case, since str[9] is a local variable, the compiler will simply assign 9 extra bytes on the stack when entering the function by shifting the stack pointer, which is a LOT faster than allocating stuff using malloc(). (You should remember that malloc() is a C run-time library function, whereas array variables are a much lower-level part of the C language).

puji: newmang gave a perfect explanation. I'd be willing to bet that if you inspect the value of str1 after doing your strcat() you'll find it's changed, because the end of the concatenated string has overwritten the start of it.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:puji
ID: 6868281
Thanks for the response, one more thing regarding strncat,
Does strncat add a '\n' at the end of the
string?
0
 
LVL 5

Expert Comment

by:nebeker
ID: 6869222
Well, the compiler may *assign* 9 bytes, but the NEXT variable on the stack will be aligned on a 4 byte boundary, which gives pretty much the same effect, since you can easily write another 3 bytes into that char[9] variable without blowing anything up.

By the way, array variables aren't a lower part of C.  C doesn't know anything about arrays, period.  It treats them as a base pointer + an offset, that's it.

0
 
LVL 5

Expert Comment

by:nebeker
ID: 6869231
puji -

strncat will never append a \n character at the end of the string (strcat won't either).  I think you're confusing this with the '\0' (nul) character, which strncat will append to the destination string.
0
 
LVL 12

Expert Comment

by:pjknibbs
ID: 6870557
nebeker: True, but pointers are still a much lower level part of the language than malloc() is. If you try compiling a simple C program to assembly code you will NOT find any calls to malloc() in the part of the code which allocates local variables.

As for stack items being aligned on four byte boundaries, there's absolutely no reason why the compiler needs to do this. If you're using PUSH and POP to set and retrieve stack values you're limited to four byte boundaries, true, but the compiler will access local variables by reading from a direct offset to the EBP register--no PUSH or POP operations are involved. It might well be that the compiler WILL doubleword-align the variables for faster access, but there's absolutely nothing forcing it to do so.
0
 

Expert Comment

by:rpatna
ID: 6873835
if u see the code of strcat();
then u can understand urself only
why it not give "Application Error"
and why it run successfully without any error.
0
 

Author Comment

by:puji
ID: 6886636
To nebeker
>>strncat will never append a \n character at the end of >>the string (strcat won't either).  I think you're
>>confusing this with the '\0' (nul) character, which >>strncat will append to the destination string.


Hi nebeker

I just wrongly typed as '\n'. But I meant '\0', null character.

So Is it true that all c compilers, (or atleast the one MSVC uses) adds a '\0' to the destination string after doing a concatenation.

Thanks
puji
0
 
LVL 4

Expert Comment

by:newmang
ID: 6887071
Yes
0
 
LVL 12

Expert Comment

by:pjknibbs
ID: 6887980
Yes, because that's how the strcat() function is defined and written in all cases.
0
 

Expert Comment

by:osnat
ID: 6892018
a) The program does not check run-time errors. U can also use free on a pointer and then use it. U can do what ever u want with pointers, but it is your responsibility ! If the memory is not used by the OS of any other application, then your program will run. BUT this is a chance u, as a programmer, can not take.

b)regarding strcat: since strcat add str2 at the end of str1, u can not define str1 as char*. and why not?!
when u define char* str1 = "test"; u are allocating 5 chars for str1 (strlen("test") + 1 for null terminator).
And str1 shoule be long enough to hold the combination of str1 and str2. there for: the compiler will have no problems with it, since strcat takes (char* str1, const char*str2), but in run-time your program will crash.
0
 
LVL 5

Expert Comment

by:nebeker
ID: 6892069
osnat -

Your answer adds absolutely nothing to the discussion - why did you even bother to post this as an answer instead of a comment?
0
 
LVL 12

Expert Comment

by:pjknibbs
ID: 6893378
nebeker: Because he's seen there's been no activity in this thread for three days and he thinks he can camp out in it and get an automatic answer awarded to him, I imagine.
0
 

Author Comment

by:puji
ID: 6897124
Hello All,

Thanks for your repsonses.
I believe I haven't worded by question .
Actually I wanted to know
Is there any difference in the '\0' null character
getting appended with respect to strcat and strncat().

Why Iam specific about this case is I came across a
program where STRNCAT function worked when I added a
null character to it, but it did NOT work (gave an error)
without the explicit additon of '\0'.

Thanks
puji
0
 
LVL 5

Expert Comment

by:nebeker
ID: 6897354
puji -

What platform and compiler are you using?  It is possible that strncat doesn't append a null in some cases -- depending on your particular compiler, that is...
0
 
LVL 4

Expert Comment

by:newmang
ID: 6897764
puji

It would be simple for you to add the trailing null anyway as follows

len=strlen(str1);
len+=strlen(str2);
strncat(str1,str2,sizeof(str1));
if(len<sizeof(str1))
    str1[len-1]=0x00;
else
    str1[sizeof(str1)-1]=0x00;

Cheers - Gavin
0
 

Author Comment

by:puji
ID: 6899840
Hi

Iam using MSVC that comes with Visual Studio 6.0 on
Windows NT 4.0 Platform.

0
 
LVL 5

Accepted Solution

by:
nebeker earned 50 total points
ID: 6899923
As long as both strings are null terminated, you won't have a problem with strncat.

Here's the reference page from Microsoft on strncat:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_strncmp.2c_.wcsncmp.2c_._mbsncmp.asp

It says:

The strncat function appends, at most, the first count characters of strSource to strDest. The initial character of strSource overwrites the terminating null character of strDest. If a null character appears in strSource before count characters are appended, strncat appends all characters from strSource, up to the null character. If count is greater than the length of strSource, the length of strSource is used in place of count. The resulting string is terminated with a null character. If copying takes place between strings that overlap, the behavior is undefined.


If you've run into a problem with this before, it most likely happened because the 2nd string wasn't null terminated...
0
 

Author Comment

by:puji
ID: 6929526
Thanks To All of You, But I would like to give points to
nebeker since it clarified my doubt.

Thanks
Puji
0
 

Author Comment

by:puji
ID: 6929528
Thanks nebeker

Bye
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

623 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question