#include<stdio.h>
#include<stdlib.h>
#include<string.h>
main()
{
char str[5]={'\0'};
printf("Initial length before passing = %ld\n",strlen(str));
input(str);
printf("Received string = %s\n",str);
printf("Length after getting input(calling function) = %ld\n",sizeof(str));
}
input(char * buffer)
{
puts("Enter something: ");
printf("Initial length after passing = %ld\n",strlen(buffer));
if ( fgets(buffer, sizeof(buffer), stdin) == NULL )
return -1;
else
{
printf("Length after getting input(called function)= %ld\n",strlen(buffer));
return 0;
}
}
Output 1
Initial length before passing = 0
Enter something:
Initial length after passing = 0
hello
Length after getting input(called function)= 6
Received string = hello
Length after getting input(calling function) = 5
Output 2
Initial length before passing = 0
Enter something:
Initial length after passing = 0
helloooooo
Length after getting input(called function)= 7
Received string = hellooo
Length after getting input(calling function) = 5
Why is it printing different lengths in when I gave different input?
In output 1 & 2 why the initial length is 6 when I allocated space for only 5 characters?
Why is the length of string different before passing and after passing in both output 1 and output 2?
In output 2 why "Length after getting input(called function)= 7" when I allocated only less space?
strlen was supposed to be working with C strings, that is, char arrays that ends with \0. When you define:
char str[5];
str contains garbage, you are lucky calling strlen didn't cause segmentation fault.
1) In output 1 & 2 why the initial length is 6 when i allocated space for only 5 characters?
Your first strlen(str) call isn't really even defined since you declared char str[5] but didn't put anything into it. So the contents are who-knows-what. That fact that strlen(str) returned a 6 just means that there happened to be 6 non-zero characters in memory, starting at address str before it encountered a 0.
2) why the length of string is different before passing and after passing in both output 1 and output 2?
After getting a length of 6 for random memory contents, you loaded something into the string buffer and zero terminated it. So the length changed to something real.
3) In output 2 why "Length after getting input(called function)= 7" when i allocated only less space?
Because you actually overran your allocated space with a longer string (of length 7). You were lucky the program didn't crash in that case.
When you declare a buffer in C, such as:
char str[5];
All it does is tell the compiler you're reserving 5 bytes of space to do something and it entitles you to use that space and only that space for str. It doesn't necessarily have anything in the buffer to start unless you put something there, and it doesn't prevent you from writing more than you declared.
Note that str[5] isn't big enough to hold "hello" since strings in C are zero-terminated. So you need a character buffer of size N+1 to hold a string of size N. When you overflow buffers in C, your results will become erratic and unpredictable.
char str[5];
printf("Initial length before passing = %ld\n",strlen(str));
strlen returns the length of specified string, not the size of the buffer. You didn't initialize str to anything, so it's full of garbage. strlen will return the "length" of that garbage, which could be anything.
Related
I have a simple error that I know lies underneath my C code's memory usage, because the iterator in a simple for loop changes drastically after receiving user input on the command line:
int i = 1;
char input[] = "";
for (i = 1; i <= 5; i++) {
printf("i %d\n> ", i);
scanf("%s", input);
printf("input %s\ni %d\n", input, i);
}
The output should be simple enough:
i 1
> <receive input>
input <input>
i 1
to be repeated 5 times.
However, the iterator 'i' changes to anything but what is expected when any input is received.
An example output:
i 1
> 45
input 45
i 53
I have a hunch that this comes from memory access in the compiler. Anything helps!
scanf("%s", input);
From the docs of scanf:
%s Matches a sequence of bytes that are not white-space characters. The application shall ensure that the corresponding argument is a pointer to the initial byte of an array of char, signed char, or unsigned char large enough to accept the sequence and a terminating null character code, which shall be added automatically.
You are the application. char input[] = ""; is only 1 byte big.
Any character returned by the scanf will result in overflowing input due to the null terminator. And will write over the next variable in memory.
Try:
char input[100] = "";
scanf("%100s", input);
Look at how your local variables are declared:
int i = 1;
char input[] = "";
input is a zero-length string, and there's no room allocated for the input you're about to ask for. When you do:
scanf("%s", input);
the input gets written into the array pointed to by input, but since there was no space reserved for that, whatever happens to be after the array that input refers to gets written over. In this case, that's I.
To solve the problem, you need to make sure that there's enough room for the input at the location where you're putting it. Also, you should limit the allowable length of the input so that the user can't enter more data than the size of the space you've reserved.
I'm very new to C and am a bit confused as to when we need to manually add the terminating '\0' character to strings. Given this function to calculate string length (for clarity's sake):
int stringLength(char string[])
{
int i = 0;
while (string[i] != '\0') {
i++;
}
return i;
}
which calculates the string's length based on the null terminating character. So, using the following cases, what is the role of the '\0' character, if any?
Case 1:
char * stack1 = "stack";
printf("WORD %s\n", stack1);
printf("Length %d\n", stringLength(stack1));
Prints:
WORD stack
Length 5
Case 2:
char stack2[5] = "stack";
printf("WORD %s\n", stack2);
printf("Length %d\n", stringLength(stack2));
Prints:
WORD stack���
Length 8
(These results vary each time, but are never correct).
Case 3:
char stack3[6] = "stack";
printf("WORD %s\n", stack3);
printf("Length %d\n", stringLength(stack3));
Prints:
WORD stack
Length 5
Case 4:
char stack4[6] = "stack";
stack4[5] = '\0';
printf("WORD %s\n", stack4);
printf("Length %d\n", stringLength(stack4));
Prints:
WORD stack
Length 5
Case 5:
char * stack5 = malloc(sizeof(char) * 5);
if (stack5 != NULL) {
stack5[0] = 's';
stack5[1] = 't';
stack5[2] = 'a';
stack5[3] = 'c';
stack5[4] = 'k';
printf("WORD %s\n", stack5);
printf("Length %d\n", stringLength(stack5));
}
free(stack5);
Prints:
WORD stack
Length 5
Case 6:
char * stack6 = malloc(sizeof(char) * 6);
if (stack6 != NULL) {
stack6[0] = 's';
stack6[1] = 't';
stack6[2] = 'a';
stack6[3] = 'c';
stack6[4] = 'k';
stack6[5] = '\0';
printf("WORD %s\n", stack6);
printf("Length %d\n", stringLength(stack6));
}
free(stack6);
Prints:
WORD stack
Length 5
Namely, I would like to know the difference between cases 1, 2, 3, and 4 (also why the erratic behavior of case 2 and no need to specify the null-terminating character in 1 and 3. Also, how 3 and 4 both work the same?) and how 5 and 6 print out the same thing even though not enough memory is allocated in case 5 for the null-terminating character (since only 5 char slots are allocated for each letter in "slack", how does it detect a '\0' character, i.e. the 6th character?)
I'm so sorry for this absurdly long question, it's just I couldn't find a good didactic explanation on these specific instances anywhere else
The storage for a string must always leave room for the terminating null character. In some of your examples you don't do this, explicitly giving a length of 5. In those cases you will get undefined behavior.
String literals always get the null terminator automatically. Even though strlen returns a length of 5, it is really taking 6 bytes.
Your case 5 only works because undefined sometimes means looking like it worked. You probably have a value of zero following the string in memory - but you can't rely on that.
In case 1, you are creating a string literal (a constant which will be on read only memory) which will have the \0 implicitly added to it.
Since \0's position is relied upon to find the end of string, your stringLength() function prints 5.
In case 2, you are trying to initialise a character array of size 5 with a string of 5 characters leaving no space for the \0 delimiter. The memory adjacent to the string can be anything and might have a \0 somewhere. This \0 is considered the end of string here which explains those weird characters that you get. It seems that for the output you gave, this \0 was found only after 3 more characters which were also taken into account while calculating the string length. Since the contents of the memory change over time, the output may not always be the same.
In case 3, you are initialising a character array of size 6 with a string of size 5 leaving enough space to store the \0 which will be implicitly stored. Hence, it will work properly.
Case 4 is similar to case 3. No modification is done by
char stack4[5] = '\0';
because size of stack4 is 6 and hence its last index is 5. You are overwriting a variable with its old value itself. stack4[5] had \0 in it even before you overwrote it.
In case 5, you have completely filled the character array with characters without leaving space for \0. Yet when you print the string, it prints right. I think it is because the memory adjacent to the memory allocated by malloc() merely happened to be zero which is the value of \0. But this is undefined behavior and should not be relied upon. What really happens depends on the implementation.
It should be noted that malloc() will not initialise the memory that it allocates unlike calloc().
Both
char str[2]='\0';
and
char str[2]=0;
are just the same.
But you cannot rely upon it being zero. Memory allocated dynamically could be having zero as the default value owing to the working of the operating system and for security reasons. See here and here for more about this.
If you need the default value of dynamically allocated memory to be zero, you can use calloc().
Case 6 has the \0 in the end and characters in the other positions. The proper string should be displayed when you print it.
I was playing around with memmove and I understand how it works. But whenever the end result contains more than the original source size, it prints out a bunch of random numbers. For example:
char str[] = "abcdefgh";
memmove(str + 6, str + 3, 4);
printf("%s\n", str);
gives me the output abcdefdefgbdefggh when it should give me
abcdefdefg Why is the other characters being added into str?
memmove(void *destination, void *source, size_t bytesToCopy)
The other characters added to the string are characters beyond the memory location of your declared char str[]. You have gone beyond the buffer address in memmove and the terminating character of '\0' has been over written. So when you call printf, the function will continue to print characters referenced by your pointer till it encounters '\0'.
The memory for str looks:
'a','b','c','d','e','f','g','h',0x0,?,?,?
^
End of buffer (terminates the string)
You copy 4 bytes from index 3 to index 6 which gives
'a','b','c','d','e','f','d','e','f','g',?,?
^
End of buffer
So you have
a) overwritten the string termination (0x0) by 'f'
b) written outside the buffer (i.e. 'g') which is really bad
Due to a) you'll get strange results when printing str as the string termination is gone.
In my code below:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define BLOCKSIZE 256;
int main()
{
char text[BLOCKSIZE];
char *new_line;
new_line=strcpy(text,"hello");
int i;
for(i=0;i<sizeof(text)/sizeof(char);i++)
{
printf("%c",*(new_line+i));
}
return 0;
}
I am trying to print the string "hello" on screen using a pointer which points to the address of the char array text. But in my code I get the string hello continued by some garbage values and then leads to core dumped. Can anyone show me the right way? Thanks
for(i=0;i < sizeof(text)/sizeof(char);i++)
The size of text is 256 bytes as you have allocated 256 bytes to it. sizeof(text)/sizeof(char) would return a value much greater than the size of "hello". That is why the loop is printing garbage values after "hello". You should use i < strlen(text) instead.
You are printing out all 256 characters of your text array. You only want to iterate up to the length of the string, like this:
for(i = 0; i < strlen(text); i++)
{
...
}
As well stated by #tourniquet_grab, code is printing beyond the end of "Hello"
Code copies "Hello" into the ample sized text[], but only the first 6 char (up to and including the terminating null character '\0'). The pointer returned by strcpy() is the address of the first char of text. The remaining 250 char of text has not been initialized. So the following prints "Hello", a '\0' and 250 pieces of junk.
new_line = strcpy(text,"hello");
for(i=0;i<sizeof(text)/sizeof(char);i++) {
printf("%c",*(new_line+i));
}
More sensible to print the string contents of new_line - only up to, but not including the terminating null character '\0'. This method will change the pointer of new_line.
new_line = strcpy(text,"hello");
// Continue looping until \0 reached
while (*new_line) {
printf("%c", *new_line++);
}
Minor points:
sizeof(char) is always 1. Rarely useful to code that. If anything, code sizeof(text)/sizeof(text[0]).
Rather than printf("%c",*new_line++);, could use fputc(*new_line++, stdout) or other 1 char functions like putc()
Anyone know why printf concatenates these two variables when outputting, but only if the length of the string is not specified?
#include <stdio.h>
int main(){
char myname[3] = "tim";
char myage[3] = "ten";
printf("myname is:%s \n", myname);
printf("myage is:%s \n", myage);
}
myname is:tim
myage is:tentim
...But when I don't specify the length of the strings it seems to work as I had expected, without printing both variables.
#include <stdio.h>
int main(){
char myname[] = "tim";
char myage[] = "ten";
printf("myname is:%s \n", myname);
printf("myage is:%s \n", myage);
}
myname is:tim
myage is:ten
You declare the array to have size 3 but you try to store 4 elements in it. Since there is enough memory for only 3 elements there is no memory left for the last element(the string null terminator \0), this leaves your character array without a null terminator.
Note that character arrays in c are expected to be null terminated so that you can print them using printf. This is because printf simply walks through the character array till it encounters a \0. In your first example since the array was never \0 terminated what you end up getting is Undefined behavior.(Practically, pintf will keep printing till it encounters a \0 and in the process reading beyond the bounds of memory allocated to the array)
In second case since you do not specify the size by yourself the appropriate size is chosen depending on the number of elements specified in the string i.e: 4 and the \0 terminate is in place.
You are not leaving enough room in your array for the null terminator. In C, when you initialize a char array with a string of the exact same length, the null terminator is dropped.
char myname[3] = "tim"; // equivalent to char myname[3] = {'t','i','m'};
char myage[3] = "ten"; // equivalent to char myage[3] = {'t','e','n'};
Without the null terminator, the printf function doesn't know when to stop printing your string, so it keeps going to the next memory location after your myage array, which just happens to be the storage for your myname array. The stack probably looks like this:
t <- beginning of myage
e
n
t <- beginning of myname
i
m
\0 <- a null terminator, by coincindence.
The fact that you don't get other garbage after the name is just a coincidence. Anything might be stored after your myname array, but in your case it was a null character, so printf stopped printing.
If you don't specify a size for your array, then a size is chosen that is one greater than the length of the string so that the null terminator can be stored:
char myname[] = "tim"; // equivalent to myname[4] = {'t','i','m','\0'};
char myage[] = "ten"; // equivalent to myage[4] = {'t','e','n','\0'};
Now your null terminators are put in place explicitly, and your stack looks like this:
t <- beginning of myage
e
n
\0 <- explicit null terminator
t <- beginning of myname
i
m
\0 <- explicit null terminator.
Now the printf function knows exactly when to stop printing.
The %s directive corresponds to an argument that points to a string. A string is a sequence of characters that ends at the first '\0'. However, you aren't giving the arrays in the first example enough space for a '\0', so those arrays don't contain strings.
printf thinks that a string exists, and continues printing characters until it comes to that '\0' character which belongs at the end of a string. As previously stated, there is no '\0' character because there isn't space for one. Your code causes printf to access bytes outside of the bounds of your arrays, which is undefined behaviour.
The myname[3] and myage[3] suppose to have a place for terminating \0. Thus, you can actually store only 2 symbols in each array.
In the second case compiler automatically sets size equal to 4 that is enough to store the strings.