C, pointer, string - c

main()
{
char *x="girl";
int n,i;
n=strlen(x);
*x=x[n];
for(i=0;i<n;i++)
{
printf("%s \n",x);
x++;
}
}
What is the output?
Please explain the output.......................
o/p is :
irl
rl
l

The output is undefined behaviour. You modified a string literal.

As others have pointed out, the program as written has undefined behaviour.
If you make a small alteration:
char x[] = "girl";
then I believe it is legal, and possible to explain. (EDIT: Actually there are still problems with it. It's int main(), and you should return 0; at the end. You also need to #include <string.h> because you are using strlen, and #include <stdio.h> because you are using printf.)
The line
*x = x[n];
sets x[0] (i.e. *x) to x[4] (which happens to be the string terminator '\0'). Thus the first string to be printed is the empty string, because the very first character is the string terminator.
We then loop through the string, one character at a time, printing the substrings:
irl
rl
l

While the result is undefined behavior, as DeadMG said, let's assume you declared x as char x[] = "girl".
You assign 4 to n (since the length of the word "girl" is 4), and you assign the value in x[4] to *x (which is x[0]), but this value is '\0' (null terminator)
Now you loop and print the word from x to the next null terminator, but the first time, the first char is the null terminator, so you get nothing. after that you print the word from incrementing index.
g i r l \0
*x = x[4]:
\0 i r l \0
^ ^ ^ ^
it1 it2 it3 it4 // << Where does x points to in each iteration of the for loop

The code is distictly suspect. *x=x[n] attempts to overwrite the literal "girl", and the effect will vary between platforms and compilers. More correctly it should be declared as:
const char *x = "girl";
and then it will not (should not) compile.

Related

Adding an integer to C-String while printing

int main(){
printf("hello world"+2);
}
test.c:32:25: warning: adding 'int' to a string does not append to the string
[-Wstring-plus-int]
printf("hello world"+2);
~~~~~~~~~~~~~^~
test.c:32:25: note: use array indexing to silence this warning
printf("hello world"+2);
^
& [ ]
1 warning generated.
alpha#Desktop % ./a.out
llo world%
So this is what I am getting. And if I increase the number then it is simply slicing the string by that.Can anyone explain this output and why it's happening to me?
In the C and C++ languages, every string that has been defined with double quotes is of type char* (pointer to char) as a statically allocated char array. When you call printf() on such string it does something like this:
void printf(char* str) {
while(*str!= '\0') {
// write the current character to stdout
write(STDOUT_FILENO, str, sizeof(char));
str ++;
}
}
I don't know if it really is written that way, indeed it probably isn't, the functionality is the same. It iterates over the string until it finds the null-terminator ('\0'). All pointers are almost equivalent to long and when you add a number to them, it increments their underlying value with sizeof(type), where type is the type of value the pointer points towards. Thus, when you add a number to "Hello World", makes printf() think your string starts on a different memory address and prints 'llo World'.
If you want to print the string with the value '2' appended to the end of it, as #Elliott Frisch stated, you would use print("Hello World%d", 2).
I would suggest looking at sprintf() and strcat() for string concatenation in C.
In C, what we might think of as a string is actually an array of characters. What you pass to printf() in both cases is a pointer to the start of such an array. You can do arithmetic with pointers, which is what you are doing here.
Here's some clarification.
#include <stdio.h>
int main(void) {
// A
printf("Hello, world!\n");
// B
printf("Hello, world!\n" + 2);
}
Output:
Hello, world!
llo, world!
In case A, you point to the start of an array containing the H character, and it reads until the last one (which is in fact a 'this is the end'-character: \0).
⬇️
H
e
l
l
o
,
w
o
r
l
d
!
\n
\0
In case B, you add 2 to the pointer before passing it to printf(). Now printf() starts reading here:
⬇️
H
e
l
l
o
,
w
o
r
l
d
!
\n
\0
This is what causes your 'slice'.

Unexplainable behaviour when printing out strings in C

The following code works as expected and outputs ABC:
#include <stdio.h>
void printString (char toPrint [100]);
int main()
{
char hello [100];
hello[0] = 'A';
hello[1] = 'B';
hello[2] = 'C';
hello[3] = '\0';
printString(hello);
}
void printString (char toPrint [100])
{
int i = 0;
while (toPrint[i] != '\0')
{
printf("%c", toPrint[i]);
++i;
}
}
But if I remove the line that adds the null-character
hallo[3] = '\0';
I get random output like wBCÇL, ╗BCÄL, ┬BCNL etc.
Why is that so? What I expected is the loop in printString() to run forever because it doesn't run into a '\0', but what happend to 'A', 'B' and 'C'? Why do B and C still show up in the output but A is replaced by some random character?
You declaration of hello leaves it uninitialized and filled with random bytes
int main()
{
char hello [100];
...
}
If you want zero initialized array use
int main()
{
char hello [100] = {0};
...
}
There must have been, by pure chance, the value for \r somewhere in the memory cells following those of my array hello. That's why my character 'A' was overwritten.
On other machines, "ABC" was ouput as expected, followed by random characters.
Initializing the array with 0s, purposely omitted here, of course solves the problem.
edit:
I let the code print out each character in binary and toPrint[5] was indeed 00001101 which is ASCII for \r (carriage return).
When you declare an automatic like char hello [100];, the first thing to understand is that the 100 bytes can contain just about anything. You must assign values to each byte explicitly to do / have something meaningful.
You are terminating you loop when you find the \0 a.k.a the NUL character. Now, if you comment out the instruction which puts the \0 after the character c, your loop runs until you actually find \0.
Your array might contain \0 at some point or it might not. There are chances you might go beyond the 100 bytes still looking for a \0 and invoke undefined behaviour. You also invoke UB when you try to work with an unassigned piece of memory.

Assignment after initialization to specific index in an array

After assigning 26th element, when printed, still "Computer" is printed out in spite I assigned a character to 26th index. I expect something like this: "Computer K "
What is the reason?
#include <stdio.h>
int main()
{
char m1[40] = "Computer";
printf("%s\n", m1); /*prints out "Computer"*/
m1[26] = 'K';
printf("%s\n", m1); /*prints out "Computer"*/
printf("%c", m1[26]); /*prints "K"*/
}
At 8th index of that string the \0 character is found and %s prints only till it finds a \0 (the end of string, marked by \0) - at 26th the character k is there but it will not be printed as \0 is found before that.
char s[100] = "Computer";
is basically the same as
char s[100] = { 'C', 'o', 'm', 'p', 'u','t','e','r', '\0'};
Since printf stops when the string is 0-terminated it won't print character 26
Whenever you partially initialize an array, the remaining elements are filled with zeroes. (This is a rule in the C standard, C17 6.7.9 §19.)
Therefore char m1[40] = "Computer"; ends up in memory like this:
[0] = 'C'
[1] = 'o'
...
[7] = 'r'
[8] = '\0' // the null terminator you automatically get by using the " " syntax
[9] = 0 // everything to zero from here on
...
[39] = 0
Now of course \0 and 0 mean the same thing, the value 0. Either will be interpreted as a null terminator.
If you go ahead and overwrite index 26 and then print the array as a string, it will still only print until it encounters the first null terminator at index 8.
If you do like this however:
#include <stdio.h>
int main()
{
char m1[40] = "Computer";
printf("%s\n", m1); // prints out "Computer"
m1[8] = 'K';
printf("%s\n", m1); // prints out "ComputerK"
}
You overwrite the null terminator, and the next zero that happened to be in the array is treated as null terminator instead. This code only works because we partially initialized the array, so we know there are more zeroes trailing.
Had you instead written
int main()
{
char m1[40];
strcpy(m1, "Computer");
This is not initialization but run-time assignment. strcpy would only set index 0 to 8 ("Computer" with null term at index 8). Remaining elements would be left uninitialized to garbage values, and writing m1[8] = 'K' would destroy the string, as it would then no longer be reliably null terminated. You would get undefined behavior when trying to print it: something like garbage output or a program crash.
In C strings are 0-terminated.
Your initialization fills all array elements after the 'r' with 0.
If you place a non-0 character in any random field of the array, this does not change anything in the fields before or after that element.
This means your string is still 0-terminated right after the 'r'.
How should any function know that after that string some other string might follow?
That's because after "Computer" there's a null terminator (\0) in your array. If you add a character after this \0, it won't be printed because printf() stops printing when it encounters a null terminator.
Just as an addition to the other users answers - you should try to answer your question by being more proactive in your learning. It is enough to write a simple program to understand what is happening.
int main()
{
char m1[40] = "Computer";
printf("%s\n", m1); /*prints out "Computer"*/
m1[26] = 'K';
for(size_t index = 0; index < 40; index++)
{
printf("m1[%zu] = 0x%hhx ('%c')\n", index, (unsigned char)m1[index], (m1[index] >=32) ? m1[index] : ' ');
}
}

sizeof() showing different output

Here is a snippet of C99 code:
int main(void)
{
char c[] = "\0";
printf("%d %d\n", sizeof(c), strlen(c));
return 0;
}
The program is outputting 2 0. I do not understand why sizeof(c) implies 2 seeing as I defined c to be a string literal that is immediately NULL terminated. Can someone explain why this is the case? Can you also provide a (some) resource(s) where I can investigate this phenomenon further on my own time.
didn't understand why size of is showing 2.
A string literal has an implicit terminating null character, so the ch[] is actually \0\0, so the size is two. From section 6.4.5 String literals of the C99 standard (draft n1124), clause 5:
In translation phase 7, a byte or code of value zero is appended to each multibyte
character sequence that results from a string literal or literals
As for strlen(), it stops counting when it encounters the first null terminating character. The value returned is unrelated to the sizeof the array that is containing the string. In the case of ch[], zero will be returned as the first character in the array is a null terminator.
In C, "" means: give me a string and null terminate it for me.
For example arr[] = "A" is completely equivalent to arr[] = {'A', '\0'};
Thus "\0" means: give me a string containing a null termination, then null terminate it for me.
arr [] = "\0"" is equivalent to arr[] = {'\0', '\0'};
"\0" is not the same as "". String literals are nul-terminated, so the first is the same as the compound literal (char){ 0, 0 } whereas the second is just (char){ 0 }. strlen finds the first character to be zero, so assumes the string ends. That doesn't mean the data ends.
When you declare a string literal as :
char c[]="\0";
It already has a '\0' character at the end so the sizeof(c) gives 2 because your string literal is actually : \0\0.
strlen(c) still gives 0 because it stops at the first \0.
strlen measures to the first \0 and gives the count of characters before the \0, so the answer is zero
sizeof on a char x[] gives the amount of storage used in bytes which is two, including the explict \0 at the end of the string
Great question. Consider this ...
ubuntu#amrith:/tmp$ more x.c
#include <stdio.h>
#include <string.h>
int main() {
char c[16];
printf("%d %d\n",sizeof(c),strlen(c));
return 0;
}
ubuntu#amrith:/tmp$ ./x
16 0
ubuntu#amrith:/tmp$
Consider also this:
ubuntu#amrith:/tmp$ more x.c
#include <stdio.h>
#include <string.h>
int main() {
int c[16];
printf("%d\n",sizeof(c));
return 0;
}
ubuntu#amrith:/tmp$ ./x
64
ubuntu#amrith:/tmp$
When you initialize a variable as an array (which is effectively what c[] is), sizeof(c) will give you the allocated size of the array.
The string "\0" is the literal string \NUL\NUL which takes two bytes.
On the other hand, strlen() computes the string length which is the offset into the string of the first termination character and that turns out to be zero and hence you get 2, 0.

Unexpected C code output

This is my c code:
#include <stdio.h>
int main(){
int x[] = {6,1,2,3,4,5};
int *p=0;
p =&x[0];
while(*p!='\0'){
printf("%d",*p);
p++;
}
return 0;
}
When run the output is 612345-448304448336
What are the digits after the minus sign and why is my code giving this?
The condition *p != '\0', which is the same as *p != 0, is never met because your array doesn't contain an element of value 0, and thus you overrun the array bounds and step into undefined behaviour.
Instead, you should control the array range directly:
for (int const * p = x; p != x + sizeof(x)/sizeof(x[0]); ++p) // or "p != x + 6"
{
printf("%d", *p);
}
You run the loop till you encounter a \0 but your array was never \0 terminated.
int x[] = {6,1,2,3,4,5};
creates an array which is not \0 terminated. You will have to explicitly add a \0 as the last element.
Since the array is not \0 terminated the while() loops run until a random \0 is encountered. Technically, this is Undefined Behavior because you are reading the contents of memory which is not allocated to your variable.
Suggested Solution:
int x[] = {6,1,2,3,4,5,0};
while(*p != 0)
Arrays in C are not Null Terminated. Which is why your loop goes beyond the end of your declared array. The digits follows 5 are just whatever happens to be in that memory space. If there hadn't been a null character following your allocation of the array the loop would have continued running until it made a SegFault.

Resources