I was making a basic program of strings and did this. There is a string in this way:
#include<stdio.h>
int main()
{
char str[7]="network";
printf("%s",str);
return 0;
}
It prints network.In my view, it should not print network. Some garbage value should be printed because '\0' does not end this character array. So how it got printed? There were no warning or errors too.
That's because
char str[7]="network";
is the same as
char str[7]={'n','e','t','w','o','r','k'};
str is a valid char array, but not a string, because it's no null-terminated. So it's undefined behavior to use %s to print it.
Reference: C FAQ: Is char a[3] = "abc"; legal? What does it mean?
char str[7]="network";
This Invokes Undefined behavior.
You did not declared array with enough space
This should be
char str[8]="network";
char str[7]="network";
you did not provide enough space for the string
char str[8]="network";
It's possible that stack pages start off completely zeroed in your system, so the string is actually null-terminated in memory, but not thanks to your code.
Try looking at the program in memory using a debugger, reading your platform documentation or printing out the contents of str[7] to get some clues. Doing so invokes undefined behavior but it's irrelevant when you're trying to figure out what your specific compiler and OS are doing at one given point in time.
Related
I am trying to test something and I made a small test file to do so. The code is:
void main(){
int i = 0;
char array1 [3];
array1[0] = 'a';
array1[1] = 'b';
array1[2] = 'c';
printf("%s", array1[i+1]);
printf("%d", i);
}
I receive a segmentation error when I compile and try to run. Please let me know what my issue is.
Please let me know what my issue is. ? firstly char array1[3]; is not null terminated as there is no enough space to put '\0' at the end of array1. To avoid this undefined behavior increase the size of array1.
Secondly, array1[i+1] is a single char not string, so use %c instead of %s as
printf("%c", array1[i+1]);
I suggest you get yourself a good book/video series on C. It's not a language that's fun to pick up out of the blue.
Regardless, your problem here is that you haven't formed a correct string. In C, a string is a pointer to the start of a contiguous region of memory that happens to be filled with characters. There is no data whatsoever stored about it's size or any other characteristics. Only where it starts and what it is. Therefore you must provide information as to when the string ends explicitly. This is done by having the very last character in a string be set to the so called null character (in C represented by the escape sequence '\0'.
This implies that any string must be one character longer than the content you want it to hold. You should also never be setting up a string manually like this. Use a library function like strlcpy to do it. It will automatically add in a null character, even if your array is too small (by truncating the string). Alternatively you can statically create a literal string like this:
char array[] = "abc";
It will automatically be null terminated and be of size 4.
Strings need to have a NUL terminator, and you don't have one, nor is there room for one.
The solution is to add one more character:
char array1[4];
// ...
array1[3] = 0;
Also you're asking to print a string but supplying a character instead. You need to supply the whole buffer:
printf("%s", array1);
Then you're fine.
Spend the time to learn about how C strings work, in particular about the requirement for the terminator, as buffer overflow bugs are no joke.
When printf sees a "%s" specifier in the formatting string, it expects a char* as the corresponding argument, but you passed a char value of the array1[i+1] expression. That char got promoted to int but that is still incompatible with char *, And even if it was it has no chance to be a valid pointer to any meaningful character string...
#include<string.h>
#include<stdio.h>
void main()
{
char *str1="hello";
char *str2="world";
strcat(str2,str1);
printf("%s",str2);
}
If I run this program, I'm getting run time program termination.
Please help me.
If I use this:
char str1[]="hello";
char str2[]="world";
then it is working!
But why
char *str1="hello";
char *str2="world";
this code is not working????
You are learning from a bad book. The main function should be declared as
int main (void);
Declaring it as void invokes undefined behaviour when the application finishes. Well, it doesn't finish yet, but eventually it will.
Get a book about the C language. You would find that
char *srt1="hello";
is compiled as if you wrote
static const char secret_array [6] = { 'h', 'e', 'l', 'l', 'o', 0 };
char* srt1 = (char*) &secret_array [0];
while
char srt1[]="hello";
is compiled as if you wrote
char srt1 [6] = { 'h', 'e', 'l', 'l', 'o', 0 };
Both strcat calls are severe bugs, because the destination of the strcat call doesn't have enough memory to contain the result. The first call is also a bug because you try to modify constant memory. In the first case, the bug leads to a crash, which is a good thing and lucky for you. In the second case the bug isn't immediately detected. Which is bad luck. You can bet that if you use code like this in a program that is shipped to a customer, it will crash if you are lucky, and lead to incorrect results that will cost your customer lots of money and get you sued otherwise.
In your code.
char *srt1="hello";
you created a pointer and pointed it at a constant string. The compiler puts that in a part of memory that is marked as read-only.
So strcat will try to modifying that which cause undefined behaviour.
it has no name and has static storage duration (meaning that it lives for the entire life of the program); and a variable of type pointer-to-char, called p, which is initialized with the location of the first character in that unnamed, read-only array.
see my answer for proper understanding why it working for first and not for second case.
String literals are read-only, you cannot change them.
This:
char *srt2="world";
means srt2 (bad name, btw) is a pointer variable, pointing at memory containing the constant data "world" (and a terminating '\0' character). There's no additional room after the six characters, and you cannot even change the letters.
You need:
char str2[32] = "world";
This, on the other hand, makes str2 be an array of 32 characters, where the first 6 characters are initialized to "world" and a terminating '\0'. It's fine to append to this, since new characters can fit into the existing array, as long as you don't overstep and try to store more than 32 characters (including the terminator).
char *srt1="hello";
char *srt2="world";
when you declare string like this, it is stored in Read-only Memory!
You can't change the variables stored in Read-only memory!
When you do strcat it is trying to modify the string, which is present in read only memory. So it is not allowed here! It is "Undefined".
In your program, str1 and str2 are not supposed to be written to because they're declared as pointer to read-only memory. To see this, do 'objdump -s a.out' and you'll see the following:
Contents of section .rodata:
400640 01000200 68656c6c 6f00776f 726c6400 ....hello.world.
400650 257300 %s.
strcat tries to write to that part of memory, thus causing a segmentation fault.
You can also use an Array. Here is a simple program of mine where I faced a problem like this, but in this problem you have to declare the size of array. Like,
mahe = [10].
#include <stdio.h>
#include <stdlib.h>
int main()
{
char cname[10] = "mahe";
strcat(cname, "Karim");
printf("%s\n", cname);
return 0;
}
i'm trying to get and print a string with gets and puts but i get a segmentation fault error when i use them togheter.
this is the code i'm trying to get this working. [i type the string "prova" to test it]
int main()
{
char *s;
gets(s);
puts(s);
return 0;
}
if i change "gets" with "scanf" i get the same error.
if i change "puts" with "printf("%s", s)" i get the output.
if i declare char *s = "prova" and then puts(s) i get the output.
i also tried to change char *s; with char s[] but i get the same error.
where i'm i wrong on this? ty very much
i know gets is bad, is just bc i'm writing exercise from "C how to program, fifth edition" by Deitel and Deitel
You have multiple problems with that piece of code. To start with gets have been deprecated since the C99 standard, and in the C11 standard it has been removed. The reason is that it's not very safe, and has no bounds-checking and so can write beyond the bounds of the memory you pass to it leading to buffer overflows.
Secondly, you use the uninitialized local variable s. The value of an uninitialized variable is indeterminate, and will be seemingly random. Using an uninitialized local variable leads to undefined behavior, which often leads to crashes.
Another problem is if you initialize s to point to a literal strings. Literals strings are constant (read-only) arrays of characters, and attempting to write to it will again lead to undefined behavior.
You need to allocate some room for the string:
char s[256];
gets(s);
puts(s);
But gets is bad. (It doesn't know how big your buffer is, so what happens if more than 255 characters are read?)
The most important mistake you have is that you are declaring a char pointer, but you are not reserving the space in memory where the characters will be stored, so you got a pointer that point to some random memory adress that you should'nt use. the "right" thing to do will be:
#include <stdio.h>
#include <stdlib.h>
#define LENGHT 20
int main()
{
char *s;
s=malloc(sizeof(char)*LENGHT); //here you make the pointer point to a memory adress that you can use
gets(s);
puts(s);
free (s);
return 0;
}
But also is strongly recommend to avoid using gets because that function doesn't check for the length of the input, so use fgets instead that allow you to do that, you will only need to set the data stream to stdin.
The code will be:
#include <stdio.h>
#include <stdlib.h>
#define LENGHT 20
int main()
{
char *s;
s=malloc(sizeof(char)*LENGHT);
fgets(s,20,stdin);
puts(s);
free(s);
return 0;
}
In the below example when I define char array uninitialized and want to find the length, it's undefined behavior.
#include<stdio.h>
int main()
{
char a[250];
printf("length=%d\n",strlen(a));
}
I got "0". I don't know how? Explain it.
Luck. Whether it's good or bad luck is a matter of opinion. The contents of your array are whatever happened to already occupy that memory, and is not initialized. In your case, it happened the first byte was a '\0'.
This is, of course, undefined behavior and you can't depend on it happening this way.
You said in your example you were using an uninitialized char array to show undefined behavior, then when you got "0" you want an explanation? It's... undefined behavior.
If you got 0 for the length if just means that there happens to be a 0 as the first element of a[] in your uninitialized array. When it's an uninitialized local that means, as far as the C standards are concerened, anything can be in there, including a 0.
To address the question in your title: "Is it necessary to initialize the char array for accurate length?"
Yes, to be able to deterministically know the length of a string in a char array via the strlen() function, it is required for a null terminator to be present. That means it needs to be initialized or set in some manner or another.
As other answers say the strlen() result is more a matter of luck than defined behaviour
To find the "size" of the memory block use sizeof() instead
Note: I've also included the string.h and used a long conversion for the integers in the printf
#include<stdio.h>
#include<string.h>
int main()
{
char a[250];
printf("length=%ld\n",strlen(a));
printf("sizeof=%ld\n",sizeof(a));
}
when you define
char a[250];
The array will contains garabage contents and random.
strlen(a) count the number of not null charachter ('\0') till it find a null charachter then it stop.
so if your char a[250]; array contains garabage element and the first element is randomly set to null '\0' the strlen(a) will return 0
This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 9 years ago.
who can tell me why the code below still works? it is obvious that the str[4] is out of boundry:
#include<stdio.h>
int main(){
char str[3];
scanf("%s", str);
printf("%c\n", str[4]);
printf("%s\n", str);
return 0;
}
when it runs, enter abcdefg, it will echo the 5th char and the whole string, nothing
will be wrong, weird?
It has been declared that c/c++ doesn't do the boundary checking, while in the case above,
how should I use printf to print a c-string that the user has entered? or more generally, how to properly use a c-string that comes from users?
str[4] gives you a pointer to the memory address after the last element of your string. You can still convert this to a character, but you never know what you get and your software might crash.
Why does it work?
It doesn't "work". It might appear to be working, though; since your code (accessing an array out of bounds) invokes undefined behavior, you can get literally any result. Undefined behavior doesn't mean "it must crash".
You wrote:
when it runs, enter [abcdefg], it will echo the 5th char and the whole
string, nothing will be wrong, weird?
but I see no input reading in the code you posted:
#include<stdio.h>
int main(){
char str[3];
printf("%c\n", str[4]);
printf("%s\n", str);
return 0;
}
In any case, str[4] points to the 5-th char (byte) starting from str, so it will print any "garbage" that happens to be in that memory location when your program runs.
Accessing array items out of bounds is undefined behavior, so the exact behavior is not specified.
Just pay attention to your array bounds.