My knowledge till now was that arrays in C and CPP/C have fixed sizes. However recently I encountered 2 pieces of code which seems to contradict this fact. I am attaching the pics here. Want to hear everyone's thoughts on how these are working. Also pasting the code and doubts here:
1.
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char str1[]="Good"; //size of str1 should be 5
char str2[]="Afternoon"; //size of str2 should be 10
cout<<"\nSize of str1 before the copy: "<<sizeof(str1);
cout<<"\nstr1: "<<str1;
strcpy(str1,str2); //copying str1 into str2
cout<<"\nSize of str1 after the copy: "<<sizeof(str1);
cout<<"\nstr1: "<<str1;
return 0;
}
your text
O/P:
Size of str1 before the copy: 5
str1: Good
Size of str1 after the copy: 5
str1: Afternoon
In first snippet I am using strcpy to copy char str2[] contents that is "Afternoon" into char str1[] whose size is 5 less than size of str2. So theoritically the line strcpy(str1,str2) should give error as size of str1 is less than size of str2 and fixed. But it executes, and more surprising is the fact that even after str1 contain the word "afternoon" the size is still the same.
2.
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char first_string[10]; // declaration of char array variable
char second_string[20]; // declaration of char array variable
int i; // integer variable declaration
cout<<"Enter the first string: ";
cin>>first_string;
cout<<"\nEnter the second string: ";
cin>>second_string;
for(i=0;first_string[i]!='\0';i );
for(int j=0;second_string[j]!='\0';j )
{
first_string[i]=second_string[j];
i ;
}
first_string[i]='\0';
cout<<"After concatenation, the string would look like: "<<first_string;
return 0;
}
O/P: Enter the first string: good
Enter the second string: afternoon
After concatenation, the string would look like: goodafternoon
Here also even if I provide a string of length 20 as input to second_string[] it's still able to concatenate both the strings and put them in first_string[], even though the size of the concatenated string will be clearly greater than size of first_string[] which is 10.
I tried to assign a string of greater length to a string variable of smaller length. techincally it should not work but it worked anyway
CodePudding user response:
There are two misunderstandings here
sizeof
is the size of the array at compile time. It has nothing to do with the contents of the array. You can change the contents all you like andsizeof
will still be the same. If you want the length of a string use the functionstrlen
.Most of the time when you break the rules of C it leads to undefined behaviour. Copying a string into an array that is too small to hold that string is one example of undefined behaviour.
You said
So theoritically the line strcpy(str1,str2) should give error as size of str1 is less than size of str2 and fixed.
This is untrue. Undefined behaviour does not mean that there must be an error. It means exactly what it says, the behaviour of your program is undefined, anything could happen. That might mean an error message, or it might mean a crash, or it might mean that your program seems to work. The behaviour is undefined.
You aren't alone in thinking as you did. I reckon the purpose of sizeof
and the nature of undefined behaviour are two of the commonest beginner misunderstandings.
And to answer the question in the title. The size of a character array is fixed in C , nothing in your example contradicts that.
CodePudding user response:
I've honestly never seen a C programmer write char stringname[20] = "string";
, that just isn't the way you'd handle strings in C ⁰.
And neither would a C programmer use array notation, because well, it's not really an array you're getting, you're getting a char*
: which isn't quite the same, because sizeof
of an array is the compile time object size, which is a pointer size for a pointer, and the array length times the individual object (assuming the size is alignable, which is the case for char[]
) for an array.
Your access beyond the end of an array is simply a bug. It is undefined behaviour. A buffer overflow. A static code analyzer, quite possibly even a compiler, would tell you that this is a mortal sin. The str*
functions know literally nothing about the size of your array, they only see a pointer to the first element, and your array literally knows nothing about the length of the string it contains, which is given by the terminating zero character's position. You're mixing up two things here!
In C , you'd definitely use the std::string
class to read from cin
, exactly to avoid the problem with buffer overflows.
So, honestly: If you're a C beginner, maybe try to ignore C strings for now. It's not a C way of dealing with string data other than fixed string literals (i.e., things between ""
in your source code), and the C way of string handling is literally still the dominant cause for remote-exploitable bugs in software, far as I can tell. C is not C, and, honestly, when it comes to handling strings, for the better. Including both <string.h>
and <iostreams>
is a pretty reliable indication of a programming beginner who has access to bad guides that treat C as extended C. But that's simply not true; it's a very different programming language with some far-reaching C compatibility, but you would, and should, not mix these two languages – as a beginner, it's hard enough to learn one¹.
⁰ Technically speaking, it even feels wrong; a string literal in C is a const char
pointer, whereas it's just a char
pointer in C. C and C are not the same language.
¹If you feel like you're explaining C to people, and sometimes feel overwhelmed with making a good explanation for things to people who are not expert C programmers already, Kate Gregory made a nice talk why teaching C to teach C is a really bad idea, which I agree to, even if she overstresses a few points.