Printing a string inconsistency - c

#include <stdio.h>
void main()
{
char a[8];
a[0] = 'h';
a[1]='e';
a[2]='l';
/*a[3]='l';
a[4]='o';*/
printf("%s", a);
}
When I run this program it prints out: hel
But why is it that when I have it like this
#include <stdio.h>
void main()
{
char a[8];
a[0] = 'h';
a[1]='e';
a[2]='l';
a[3]='l';
a[4]='o';
printf("%s", a);
}
It prints out: hello��
If the string is 3 characters or less, then it prints out the string correctly but if I have more than that and no NULL character at the end(to signify the end of the string) it prints out some garbage?
Also, this is in C.

You are facing some unexpected behavior since you are not closing the string with a NUL '\0' character. In the first version when you skip the [3] address in the array it probably contains a 0 that fatally close the string, but this is absolutely random and unpredictable.

In C, dynamic (malloc...) and automatic (stack) variables are not zero-initialised. Only static and thread-local variables are zeroed.
Thus, if you do not provide the terminating 0 yourself, there might not be one, so your string is not terminated and using it results in undefined behavior.
Anyway, using indeterminate values can result in implementation defined or undefined behavior in certain cases all by itself, which might make your program misbehave erratically.

Related

Unexpected result while assigning value to a character array in dynamic memory allocation

The following program is showing unexpected result
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* num1;
num1 = malloc(100*sizeof(char));
num1 = "38462879";
printf("%s\n",num1);
num1[0]='5';
printf("%s\n",num1);
return 0;
}
I expect it to print the given string and then print the given string with the first letter replaced by 5 instead of 3 in the next line.
But it is printing the given string in first line and then the program is not going ahead.
Can you please help??
By saying
num1 = "38462879";
you're essentially
Overwriting the allocated pointer to the memory (memory leak)
Making num1 point to a string literal. (illegal to attempt to modify the content)
Later your attempt to modify a part of that literal will invoke undefined behavior. What you need instead is to use strcpy(), like
strcpy (num1, "38462879");
That said, couple of general suggestion:
for a hosted environment, int main() should at least be int main(void).
You must always check for the success of a function call (esp. library functions) before using the returned value.
in C, sizeof(char) is defined to be 1, it's a redundant multiplier.
Do not assign a constant string to num1, but use strcpy(): strcpy(num1, "whatever");
this is a character ,you can't allocate memory for one character and store a string it it , it only has space for one character . I think you meant char *num1.

Character array initialization in C

I am trying to understand the array concept in string.
char a[5]="hello";
Here, array a is an character array of size 5. "hello" occupies the array index from 0 to 4. Since, we have declared the array size as 5, there is no space to store the null character at the end of the string.
So my understanding is when we try to print a, it should print until a null character is encountered. Otherwise it may also run into segmentation fault.
But, when I ran it in my system it always prints "hello" and terminates.
So can anyone clarify whether my understanding is correct. Or does it depends upon the system that we execute.
As ever so often, the answer is:
Undefined behavior is undefined.
What this means is, trying to feed this character array to a function handling strings is wrong. It's wrong because it isn't a string. A string in C is a sequence of characters that ends with a \0 character.
The C standard will tell you that this is undefined behavior. So, anything can happen. In C, you don't have runtime checks, the code just executes. If the code has undefined behavior, you have to be prepared for any effect. This includes working like you expected, just by accident.
It's very well possible that the byte following in memory after your array happens to be a \0 byte. In this case, it will look to any function processing this "string" as if you passed it a valid string. A crash is just waiting to happen on some seemingly unrelated change to the code.
You could try to add some char foo = 42; before or after the array definition, it's quite likely that you will see that in the output. But of course, there's no guarantee, because, again, undefined behavior is undefined :)
What you have done is undefined behavior. Apparently whatever compiler you used happened to initialize memory after your array to 0.
Here, array a is an character array of size 5. "hello" occupies the array index from 0 to 4. Since, we have declared the array size as 5, there is no space to store the null character at the end of the string.
So my understanding is when we try to print a, it should print until a null character is encountered.
Yes, when you use printf("%s", a), it prints characters until it hits a '\0' character (or segfaults or something else bad happens - undefined behavior). I can demonstrate that with a simple program:
#include <stdio.h>
int main()
{
char a[5] = "hello";
char b[5] = "world";
int c = 5;
printf("%s%s%d\n", a, b, c);
return 0;
}
Output:
$ ./a.out
helloworldworld5
You can see the printf function continuing to read characters after it has already read all the characters in array a. I don't know when it will stop reading characters, however.
I've slightly modified my program to demonstrate how this undefined behavior can create bad problems.
#include <stdio.h>
#include <string.h>
int main()
{
char a[5] = "hello";
char b[5] = "world";
int c = 5;
printf("%s%s%d\n", a, b, c);
char d[5];
strcpy(d, a);
printf("%s", d);
return 0;
}
Here's the result:
$ ./a.out
helloworld��world��5
*** stack smashing detected ***: <unknown> terminated
helloworldhell�p��UAborted (core dumped)
This is a classic case of stack overflow (pun intended) due to undefined behavior.
Edit:
I need to emphasize: this is UNDEFINED BEHAVIOR. What happened in this example may or may not happen to you, depending on your compiler, architecture, libraries, etc. You can make guesses to what will happen based on your understanding of different implementations of various libraries and compilers on different platforms, but you can NEVER say for certain what will happen. My example was on Ubuntu 17.10 with gcc version 7. My guess is that something very different could happen if I tried this on an embedded platform with a different compiler, but I cannot say for certain. In fact, something different could happen if I had this example inside of a larger program on the same machine.

gets and puts to get and print a string

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;
}

pointer in c program

program in c language
void main()
{
char *a,*b;
a[0]='s';
a[1]='a';
a[2]='n';
a[3]='j';
a[4]='i';
a[5]='t';
printf("length of a %d/n", strlen(a));
b[0]='s';
b[1]='a';
b[2]='n';
b[3]='j';
b[4]='i';
b[5]='t';
b[6]='g';
printf("length of b %d\n", strlen(b));
}
here the output is :
length of a 6
length of b 12
Why and please explain it.
thanks in advance.
You are assigning to pointer (which contains garbage) without allocating memory. What you are noticing is Undefined Behavior. Also main should return an int. Also it does not make sense to try and find the length of an array of chars which are not nul terminated.
This is how you can go about:
Sample code
When you declare any variable it comes with whatever it had in memory previously where your application is running, and since pointers are essentially numbers, whatever number it had referenced to some random memory address.
Then, when setting a[i], the compiler interprets that as you want to step sizeof(a) bytes forward, thus, a[i] is equal to the address (a + i*1) (1 because chars use one byte).
Finally, C-strings need to be NULL terminated (\0, also known as sentinel), and methods like strlen go over the length of the string until hitting the sentinel, most likely, your memory had a stray 0 somewhere that caused strlen to stop.
Allocate some memory and terminate the strings then it will work better
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(){
char *a=malloc(10);
char *b=malloc(10);
if(a){
a[0]='s';
a[1]='a';
a[2]='n';
a[3]='j';
a[4]='i';
a[5]='t';
a[6]=(char)0;
printf("length of a %d\n", (int)strlen(a));
}else{
printf("Failed to allocate 10 bytes\n" );
}
if(b){
b[0]='s';
b[1]='a';
b[2]='n';
b[3]='j';
b[4]='i';
b[5]='t';
b[6]='g';
b[7]=(char)0;
printf("length of b %d\n", (int)strlen(b));
}else{
printf("Failed to allocate 10 bytes\n" );
}
free(a);
free(b);
}
Undefined behavior. That's all.
You're using an uninitialized pointer. After that, all bets are off as to what will happen.
Of course, we can attempt to explain why your particular implementation acts in a certain way but it'd be quite pointless outside of novelty.
The indexing operator is de-referencing the pointers a and b, but you never initialized those pointers to point at valid memory. Writing to un-initialized memory triggers undefined behavior.
You are simply "lucky" (or unlucky, it depends on your viewpoint) that the program doesn't crash, that the pointer values are such that you succeed in writing at those locations.
Note that you never write the termination character ('\0') to either string, but still get the "right" value from strlen(); this implies that a and b both point at memory that happens to be full of zeros. More luck.
This is a very broken program; that it manages to run "successfully" is because it's behavior is undefined, and undefined clearly includes "working as the programmer intended".
a and b are both char pointers. First of all, you didn't initialise them and secondly didn't terminate them with NULL.

String size is equal to number of characters

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.

Resources