This question already has an answer here:
How does the strlen function work internally?
(1 answer)
Closed 5 years ago.
int main(){
char s[1000];
s[0]='Q';
printf("%d",strlen(s));
return 0;
}
The above code is giving 6 as output.
The output should be 1 in this case.
int main(){
char s[1000];
printf("%d",strlen(s));
return 0;
}
This code was even giving 6 as output.
where it should be 1000 or 0 or some garbage value.
I have tried it in " hackerrank ", but it was giving 6 as the length.
When the same code was tried in TURBOC it was giving the correct answer.
I was unable to find the reason for this output. Can someone please sort it out and give the exact solution to this problem.
Local non-static variables, like your array, will not be initialized. Its value or contents will be indeterminate.
That means the likelihood of your array containing a string terminator where you want it to be is close to zero.
Passing your array without initialization to a string-function leads to undefined behavior.
You need to explicitly initialize your array, like e.g.
char s[1000] = "";
The line:
char s[1000];
declares an array of 1000 chars but it doesn't put anything in it. Because it is a local variable, it is allocated on the stack and, apart from reserving the necessary space to hold 1000 chars, the compiler doesn't generate any code to set their content (to zero or something else).
All 1000 values are garbage. It just happens that the 7th of them is zero. strlen() stops counting when it reaches it and returns 6 but this value is also garbage. It could be 230790345 or something else as well. It could also produce an infinite loop, a segmentation fault or make you spit fire like a dragon. Anything is possible and permitted by the language in this situation. It is called Undefined Behaviour.
Related
I have some trouble with strncat().The book called Pointers On C says the function ,strncat(),always add a NUL in the end of the character string.To better understand it ,I do an experiment.
#include<stdio.h>
#include<string.h>
int main(void)
{
char a[14]="mynameiszhm";
strncat(a,"hello",3);
printf("%s",a);
return 0;
}
The result is mynameiszhmhel
In this case the array has 14 char memory.And there were originally 11 characters in the array except for NUL.Thus when I add three more characters,all 14 characters fill up the memory of array.So when the function want to add a NUL,the NUL takes up memory outside the array.This cause the array to go out of bounds but the program above can run without any warning.Why?Will this causes something unexpected?
So when we use the strncat ,should we consider the NUL,in case causes the array go out of bound?
And I also notice the function strncpy don't add NUL.Why this two string function do different things about the same thing?And why the designer of C do this design?
This cause the array to go out of bounds but the program above can run without any warning. Why?
Maybe. With strncat(a,"hello",3);, code attempted to write beyond the 14 of a[]. It might go out of bounds, it might not. It is undefined behavior (UB). Anything is allowed.
Will this causes something unexpected?
Maybe, the behavior is not defined. It might work just as you expect - whatever that is.
So when we use thestrncat ,should we consider the NUL, in case causes the array go out of bound?
Yes, the size parameter needs to account for appending a null character, else UB.
I also notice the function strncpy don't add NUL. Why this two string function do different things about the same thing? And why the designer of C do this design?
The 2 functions strncpy()/strncat() simple share similar names, not highly similar paired functionality of strcpy()/strcat().
Consider that the early 1970s, memory was far more expensive and many considerations can be traced back to a byte of memory more that an hour's wage. Uniformity of functionality/names was of lesser importance.
And there were originally 11 characters in the array except for NUL.
More like "And there were originally 11 characters in the array except for 3 NUL.". This is no partial initialization in C.
This is not really an answer, but a counterexample.
Observe the following modification to your program:
#include<stdio.h>
#include<string.h>
int main(void)
{
char p[]="***";
char a[14]="mynameiszhm";
char q[]="***";
strncat(a,"hello",3);
printf("%s%s%s", p, a, q);
return 0;
}
The results of this program are dependent on where p and q are located in memory, compared to a. If they are not adjacent, the results are not so clear but if either p or q immediately comes after a, then your strncat will overwrite the first * causing one of them not to be printed anymore because that will now be a string of length 0.
So the results are dependent on memory layout, and it should be clear that the compiler can put the variables in memory in any order it likes. And they can be adjacent or not.
So the problem is that you are not keeping to your promise not to put more than 14 bytes into a. The compiler did what you asked, and the C standards guarantee behaviour as long as you keep to the promises.
And now you have a program that may or may not do what you wanted it to do.
This question already has answers here:
Space for Null character in c strings
(5 answers)
Closed 3 years ago.
I think I'm going insane because I cannot find an explanation to why C is combining my chars.
I've made you guys a test programm...
#include <stdio.h>
#include <stdlib.h>
int main()
{
char alphabet_big[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char alphabet_small[26] = "abcdefghijklmnopqrstuvwxyz";
printf("%s\n", alphabet_small);
return 0;
}
Results: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZV
Why is C combining alphabet_small and alphabet_big? That's not making sense. And why is there a "V" at the end of the char?
I hope someone can provide me an answer to this "problem".
Best regards.
Keep in mind that a C String is defined as a null terminated char array.
Change the declaration and initialization statement here: (for both statements.)
char alphabet_big[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//forces compiler to use only 26 char
//regardless of the count of initializers
//(leaving no room for NULL terminator)
To
char alphabet_big[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//allows compiler to set aside
^^ //the proper space, no matter how many initializers
The first produces undefined behavior when using with any of the string functions, such as strcpy, strcmp, and in this case printf with the "%s" format specifier.
The first produces the following, which is not is not a C string:
|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|?|?|?|
While the 2nd produces the following, which is a C string:
|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|\0|?|?|
Note - The ? symbols used in above illustration depict memory locations that are not owned by the program, and for which the contents are unknown, or may not even exist. A program attempting to access these locations would be invoking undefined behavior.
Normally the library functions expect to find a NUL byte at the end of a string, and the compiler is happy to add it for you automatically except you've told it that alphabet_big has only 26 bytes, essentially avoiding that extra NUL byte, so it combines with what's next.
Remove the 26 and let the compiler count for you.
I am writing a code to take a user's input from the terminal as a string. I've read online that the correct way to instantiate a string in C is to use an array of characters. My question is if I instantiate an array of size [10], is that 10 indexes? 10 bits? 10 bytes? See the code below:
#include <stdio.h>
int main(int argc, char **argv){
char str[10] = "Jessica";
scanf("%s", &str);
printf("%c\n", str[15]);
}
In this example "str" is initialized to size 10 and I am able to to print out str[15] assuming that when the user inputs a a string it goes up to that index.
My questions are:
Does the size of the "str" array increase after taking a value from scanf?
At what amount of string characters will my original array have overflow?
.
When you declare an array of char as you have done:
char str[10] = "Jessica";
then you are telling the compiler that the array will hold up to 10 values of the type char (generally - maybe even always - this is an 8-bit character). When you then try to access a 'member' of that array with an index that goes beyond the allocated size, you will get what is known as Undefined Behaviour, which means that absolutely anything may happen: your program may crash; you may get what looks like a 'sensible' value; you may find that your hard disk is entirely erased! The behaviour is undefined. So, make sure you stick within the limits you set in the declaration: for str[n] in your case, the behaviour is undefined if n < 0 or n > 9 (array indexes start at ZERO). Your code:
printf("%c\n", str[15]);
does just what I have described - it goes beyond the 'bounds' of your str array and, thus, will cause the described undefined behaviour (UB).
Also, your scanf("%s", &str); may also cause such UB, if the user enters a string of characters longer than 9 (one must be reserved for a terminating nul character)! You can prevent this by telling the scanf function to accept a maximum number of characters:
scanf("%9s", str);
where the integer given after the % is the maximum input length allowed (anything after this will be ignored). Also, as str is defined as an array, then you don't need the explicit "address of" operator (&) in scanf - it is already there, as an array reference decays to a pointer!
Hope this helps! Feel free to ask for further clarification and/or explanation.
One of C's funny little foibles is that in almost all cases it does not check to make sure you are not overflowing your arrays.
It's your job to make sure you don't access outside the bounds of your arrays, and if you accidentally do, almost anything can happen. (Formally, it's undefined behavior.)
About the only thing that can't happen is that you get a nice error message
Error: array out-of-bounds access at line 23
(Well, theoretically that could happen, but in practice, virtually no C implementation checks for array bounds violations or issues messages like that.)
See also this answer to a similar question.
An array declares the given number of whatever you are declaring. So in the case of:
char str[10]
You are declaring an array of ten chars.
Does the size of the "str" array increase after taking a value from scanf?
No, the size does not change.
At what amount of string characters will my original array have overflow?
An array of 10 chars will hold nine characters and the null terminator. So, technically, it limits the string to nine characters.
printf("%c\n", str[15]);
This code references the 16th character in your array. Because your array only holds ten characters, you are accessing memory outside of the array. It's anyone's guess as to if your program even owns that memory and, if it does, you are referencing memory that is part of another variable. This is a recipe for disaster.
I am making it clear that my question is exact duplicate of this question.
But unfortunately I have one question which any of the answers didn't addressed.
So the code was:-
#include <string.h>
int foo(void) {
char bar[128];
char *baz = &bar[0];
baz[127] = 0;
return strlen(baz);
}
Question was: What are the possible outputs of this function?
When I run this code, this gives 0 everytime and the correct answers are 0 and 127(I still didn't get why?).
My question is how this statement is even valid I mean we are calculating the length of baz which contains a memory address say 0xb96eb740 which is a hex number, so what we are doing is strlen() on this address to find it's length? I mean how can we find length of an address, which is just a number?
I am really confused and trying to understand it for hours but still not getting it.
Don't get stuck on the fact that it's being passed an address. strlen() always takes an address. It's argument is a const char *, the address of a string. All of these calls pass the exact same address:
strlen(baz);
strlen(&bar[0]);
strlen(bar);
baz is assigned &bar[0], so the first and second are equivalent. An array decays to a pointer to its first element (array == &array[0]), so the second and third are equivalent.
I mean how can we find length of an address, which is just a number?
Let's say that bar == &bar[0] == baz == (char *) 0xb96eb740 as per your example. strlen() will first check if memory location 0xb96eb740 contains \0. If not, it will then check 0xb96eb741. Then 0xb96eb742. Then 0xb96eb743. It will continue checking each location sequentially until it finds \0.
I know that's true. But why does strlen(baz) return 0?
As the linked Q&A explains, the behavior is indeterminate because the contents of the bar[128] array are uninitialized. There could be anything in that array. The only cell we know the value of is bar[127], which is set to \0. All the others are uninitialized.
That means that any one of them, or all of them, or none of them, could contain a \0 character. It could change from run to run, from call to call even. Every time you call foo() you could get a different result. That's entirely possible. The result will vary based on what data happens to be on the stack before foo() is called.
When I run this code, this gives 0 every time and the correct answers are 0 and 127 (I still don't get why?).
It could return any value between 0 and 127. Due to the indeterminate behavior you mustn't read too much into what the program happens to return when you run it. The output could be different if you run the program again, if you cal a different set of functions before foo(), if you run a different program beforehand, if you change compilers, if you run it a different day of the week, if you use a different operating system, etc., etc., etc.
My question is how this statement is even valid I mean we are calculating the length of baz which contains a memory address say 0xb96eb740 which is a hex number, so what we are doing is strlen() on this address to find it's length?
The strlen function accepts an address as argument, and its behaviour is to read the character stored at that address. (It does not try to read the characters of the address as you seem to be suggesting). If that character is not '\0' then it will read the character at the next address and see if that is '\0' etc.
The answer to your question is anything can happen.
The array bar is uninitialized. Only bar[127] is explicitly set to '\0'. Passing an uninitialized array to strlen(), which you do indirectly by passing baz, which points to bar[0], has undefined behavior.
In practice, on modern architectures without trap values, function foo() has unspecified behavior and can return any value between 0 and 127 depending on whatever the stack contains when you call it.
In your case it returns 0 because there happens to be a null byte at the beginning of bar, but you cannot rely on that and successive calls to foo() could return different values.
If you run a program that calls foo() under valgrind or some other memory sanitizing tool, it might complain that strlen() accesses uninitialized memory.
Others have covered that the value is indeterminate, so I go directly to this:
I mean how can we find length of an address, which is just a number?
You don't. The length of a string is calculated by reading the memory sequentially from the address you want to start with and see how far you need to go before you hit the first '\0' character. Here is an example of how you can implement a function that returns the length of a string:
int strlen(char * str) {
int length=0;
while(str[length] != '\0')
length++;
return length;
}
This question already has answers here:
sprintf buffer sizes
(3 answers)
Closed 9 years ago.
I'm having an issue with sprintf in C resetting the value of a counter variable when I run it. Here in a nutshell is what is happening:
int count = 0;
count++;
printf("%d\n", count); // count will equal 1
char title[7];
sprintf(title, "%.3d.jpg", count);
printf("%d\n", count); // count now equals 0 again
Is this normal behavior for sprintf?
title is too small, sprintf is writing beyond the bounds of title, and writing into count, corrupting its value.
Note that title needs to be long at least 8 bytes: 3 for %.3d, 4 for .jpg and 1 for the terminator \0.
As Grijesh Chauhan points out, you can make sure that you never write beyond the allocated size of the string by using snprintf, i.e.:
char title[8];
snprintf(title, sizeof(title), "%.3d.jpg", count);
You simply need more space in the string title: 3 digits+".jpg" = 7 chars, and u need one extra for '\0'(end of the string). Sprintf can change argument in a case such as this(Using sprintf will change the specified variable)
Solution: change
char title[7];
to
char title[8];
You problem is called buffer overflow. sprintf has no idea of the size of title, and write has much as needed, even if it exceeds the boundaries of your array. To fully understand, you also have to know that strings are terminated by a zero. This allows to find the end of a string, without prior knowledge of its true size. This extra zero takes the place of an extra character that you have to consider when dimensioning your buffers.
Consider also the use of snprintf that ensures you are not going over the boundaries of your buffer.