Experts there is a question given in the book "Let us C" where the author has asked to write the output of the given program.
The program is-
#include<stdio.h>
int main()
{
char s[]="Churchgate: no church no gate";
char t[40];
char *ss,*tt;
ss=s;
while(*ss!='\0')
*tt++=*ss++;
printf("%s\n",t);
return 0;
}
When I tried it on my gcc compiler, the output was core-dumped. Please explain why.Here ss and tt are character pointers.
Here I also don't understand that what's the meaning of the statement ss=s;
I mean we can't directly copy a string unless we are copying it character by character. And ss is a character pointer so it points to a character then ss=s means what? Does it mean it will point to the byte whose address is the ASCII value of s?
I also don't understand this statement *tt++=*ss++. I don't have any clue about it. Please elaborate its meaning.
Next I don't understand why printf("%s\n",t) is used as though t is of character type but it is not storing anything according to the program.
First thing first'
Array name is nothing but the pointer that holds the address of the first element.
So,
char s[]="Churchgate: no church no gate";
here s is the pointer name. And it holds the address of 'C' of the string.
Now you have declared another pointer which is also a character type i.e. ss.
so, ss=s; means ss is also holding the address which is held by s also.
As you haven't store anything to t so it will print garbage. Similarly pointer tt is not storing any address initially(Garbage).
And lastly and most importantly
you can't perform this op:
*tt++=*ss++;
probably show you error of lvalue recquired.
Related
I read that when you declare strings using a pointer, the pointer contains the memory address of the string literal. Therefore I expected to get the memory address from this code but rather I got some random numbers. Please help me understand why it didn't work.
int main()
{
char *hi = "Greeting!";
printf("%p",hi);
return(0);
}
If the pointer hi contains the memory address of the string literal, then why did it not display the memory address?
It did work. It's just that you can consider the address as being arbitrarily chosen by the C runtime. hi is a pointer set to the address of the capital G in your string. You own all the memory from hi up to and including the nul-terminator at the end of that string.
Also, use const char *hi = "Greeting!"; rather than char *: the memory starting at hi is read-only. Don't try to modify the string: the behaviour on attempting to do that is undefined.
The "random numbers" you got are the Memory addresses. They are not constant, since on each execution of your program, other Memory addresses are used.
A pointer could be represented in several ways. The format string "%p" "writes an implementation defined character sequence defining a pointer" link. In most cases, it's the pointed object's address interpreted as an appropriately sized unsigned integer, which looks like "a bunch of random number".
A user readable pointer representation is generally only useful for debugging. It allows you to compare two different representations (are the pointers the same?) and, in some cases, the relative order and distance between pointers (which pointer comes "first", and how far apart are they?). Interpreting pointers as integers works well in this optic.
It would be helpful to us if you could clarify what output you expected. Perhaps you expected pointers to be zero-based?
Note that, while some compilers might accept your example, it would be wiser to use const char *. Using a char * would allow you to try to modify your string literal, which is undefined behavior.
So I was asked these 2 questions in my interview-
1-what if I have a code snippet like this in C what will be the output
char *ptr1=malloc(10);
ptr1="abc";
char *ptr2 = malloc(20);
ptr2="defghi";
strcpy(ptr1,ptr2);
printf("%s",ptr1);
I tried this one on my terminal after getting home and it was giving this error
[1] 7673 bus error ./b.out
I would like to know how to copy the string in such a case from one pointer to another.
2- We have 2 processes A and B
This is the code in process A
char *ptr1=malloc(10);
ptr1="abc";
char *ptr2 = malloc(20);
ptr2="defghi";
strcpy(ptr1,ptr2);
now the address of ptr1 is passed to process B using interprocess communication and the code in process B is as follows (ptr1 is the address from process A)
char *ptr3=malloc(10);
ptr3=ptr1
printf("%s",ptr3);
What would be the output of this? If the ans is garbage value or error then in what way can we make ptr3 point to the string pointed by ptr1.
I would like to know how to copy the string in such a case from one pointer to another.
You can't. Pointers do not contain strings, or their characters. They can, however, point to null-terminated arrays of characters, i.e. strings.
Having that in mind, it is important to understand that here:
char *ptr1=malloc(10);
ptr1="abc";
you allocate block of memory (or try to do), assign its address to variable ptr1, and then immediately overwrite that pointer value with a pointer to the arrary represented by string literal "abc". The original pointer value is lost -- you leak that memory. In particular, the assignment absolutely does not copy the characters of the literal into the allocated space.
Now be aware that attempting to modify any part of a string literal invokes undefined behavior, whether the modification is direct or indirect. This:
strcpy(ptr1,ptr2);
constitutes an attempt to modify string literal "abc" indirectly via pointer ptr1. If the question was "what is the output" then it was a trick question. The program has undefined behavior -- it's output cannot be predicted, at least not from the C code alone.
The IPC case is a different trick question. Pointer values are meaningful only in the context of the process in which the pointer was obtained. If you pass that pointer to a different process via some form of IPC, there is no reason to suppose that it is valid in the receiving process. Even if it happens to be valid, there's no telling what it points to. If you want to send a string to another process then you must send the characters, not the pointer.
I compiled and ran the following code and the results too are depicted below.
#include <stdio.h>
int main(void) {
char *ptr = "I am a string";
printf("\n [%s]\n", ptr);
return 0; }
** [I am a string]**
I want to understand how a string has been assigned inside a pointer char. As per my understanding the pointer can hold only an address, not a complete string. Here it is holding one whole sentence. I do not understand how being a pointer allows it to behave such way.
If I change the following line of code in the above example,
printf("\n [%c]\n", ptr);
It does not print one single charactor and stop. What it does is that it prints out an unrecognised character which is completely out of ASCII table. I do not understand how that too is happening. I would appreciate some light shred on this issue.
As per my understanding the pointer can hold only an address, not a
complete string
char *ptr = "I am a string";
Is a string literal the string is stored in the read-only location and the address in which the data is stored is returned to the pointer ptr.
It does not print one single charactor and stop. What it does is that
it prints out an unrecognised character which is completely out of
ASCII table. I do not understand how that too is happening
ptr is a pointer and using wrong format specifier in printf() lead to undefined behvaior.
With %s if you provide the address where the string is stored the printf() prints out the whole string
A pointer does not hold a string, it points to a string. (Easy to remember, it's called a "pointer", not a "holder"). To see the difference, write your postal address on a yellow sticky note. Does this piece of paper hold you? No, it points to you. It holds your address.
Pointers are computer equivalent of postal addresses (in fact things that pointers do hold are called addresses). They don't hold "real things" like strings, they tell where "real things" live.
Back to our string, the pointer actually points to the first character of the string, not to the string as a whole, but that's not a problem because we know the rest of the string lives right next to the first chsracter.
Now "%s" as a format specifier wants a pointer to the first character of a string, so you can correctly pass p to printf. OTOH %c wants a character, not a pointer, so passing p in this case leads to undefined behavior.
So how come we can say things like char* p = "abc"? String literals are arrays of characters, and an array in most cases decays into pointer to its first element. Array-to-pointer decay is another confusing property of C but fortunately there is a lot of information available on it out there. OTOH `char p = "abc" is not valid, because a character is not an array (a house is not a street).
Also
char *ptr = "I am a string";
automatically inserts a null character at the end. So when you do a printf with %s format specifier, it starts from the address of the string literal and prints upto the null character and stops.
I have learned that char *p means "a pointer to char type"
and also I think I've also learned that char means to read
that amount of memory once that pointer reaches its' destination.
so conclusively, in
char *p = "hello World";
the p contains the strings' address and
the p is pointing right at it
Qusetions.
if the p points to the string, shouldn't it be reading only the 'h'???
since it only reads the sizeof a char?
why does `printf("%s", p) print the whole string???
I also learned in Rithcie's book that pointer variables don't possess a data type.
is that true???
So your string "hello world" occupies some memory.
[h][e][l][l][o][ ][w][o][r][l][d][\0]
[0][1][2][3][4][5][6][7][8][9][A][B ]
The pointer p does, in fact, only point to the first byte. In this case, byte 0. But if you use it in the context of
printf("%s", p)
Then printf knows to print until it gets the null character \0, which is why it will print the entire string and not just 'h'.
As for the second question, pointers do posses a data type. If you were to say it outloud, the name would probably be something like type "pointer to a character" in the case of p, or "pointer to an integer" for int *i.
Pointer variables don't hold a data type, they hold an address. But you use a data type so you know how many bytes you'll advance on each step, when reading from memory using that pointer.
When you call printf, the %s in the expression is telling the function to start reading at the address indicated by *p (which does hold the byte value for 'h', as you said), and stop reading when it reaches a terminating character. That's a character that has no visual representation (you refer to it as \0 in code). It tells the program where a string ends.
Here *p is a pointer to some location in memory, that it assumes to be 1 byte (or char). So it points to the 'h' letter. So p[0] or *(p+0) will give you p. But, your string ends with invisible \0 character, so when you use printf function it outputs all symbols, starting from the one, where *p points to and till `\0'.
And pointer is just a variable, that is able to hold some address (4, 8 or more bytes).
For question:
I also learned in Rithcie's book that pointer variables don't possess a data type. is that true???
Simply put, YES.
Data types in C are used to define a variable before its use. The definition of a variable will assign storage for the variable and define the type of data that will be held in the location.
C has the following basic built-in datatypes.int,float,double,char.
Quoting from C Data types
Pointer is derived data type, each data type can have a pointer associated with. Pointers don't have a keyword, but are marked by a preceding * in the variable and function declaration/definition. Most compilers supplies the predefined constant NULL, which is equivalent to 0.
if the p points to the string, shouldn't it be reading only the 'h'???
since it only reads the sizeof a char? why does printf("%s", *p) print
the whole string???
change your printf("%s", *p) to printf("%c", *p) you see what you want. both calls the printf in different ways on the basis of format specifier i.e string(%s) or char(%c).
to print the string use printf("%s", p);
to print the char use printf("%c", *p);
Second Ans. : Pointers possesses a data type. that's why you used char *p .
I am a newbie to C programming. And I am confused with the chaotic behavior of pointers. Specially when it comes to strings and arrays.
I know that I can't write like,
#include <stdio.h>
int main()
{
int *number=5;
printf("%d",*number);
}
Because clearly it will try to write to the 5th location of the memory.And that will crash the program.I have to initialize the "number".
But when it comes to strings I can write like,
#include <stdio.h>
int main()
{
char *name="xxxxx";
printf(name);
}
And it works too. So that means it implicitly initialize the "name" pointer.I also know that name=&name[0] But I have found that name=&name too. How can it be?
Because, to me it looks two variables with the same name. Can anybody tell me how strings are created in memory?(All this time time I assumed it creates name[0].....name[n-1] and another variable(a pointer) called "name", inside that we put the location of name[0].Seem to be I was wrong.)
PS:-My English may not be good and if somebody can give me a link regarding above matter that would be grateful.
C, like many programming languages, supports the concept of "literals" - special syntax that, when encountered, causes the compiler to create a value in a special way.
-2, for example, is an integer literal. When encountered, the compiler will treat it as a value of type int with the content of -2. "..." is a string literal - when encountered, the compiler allocates new space in a special memory area, fills it with data that corresponds to the chars you used inside the literal, adds a 0 at the end of that area, and finally uses a pointer to that area, of type char*, as the result of the literal expression. So char* s = "hello" is an assignment from something of type char* into a variable of type char* - completely legal.
You sneaked in another question here - why a == &a[0]. It's best to ask one question at a time, but the gist of it is that a[n] is identical to *((a)+(n)), and so:
&a[0] == &*(a+0) == a+0 == a
char *name="xxxxx";
This creates a char array(const) in memory, and it will assign the address of 1st element of it to name. char* array names are like pointers. &name[0] means address of 1st element and name (In c,cpp just the char * array name will provide you with the address of 1st element too (bcos that is what was assigned to name in the 1st place itself)) also gives the same result.
The notation name[i] is translated as *(name+i) so u actually have a base address name to which you add subscripts. (calculations are as per pointer arithmetic) . printf("%s", name) is designed to print from start address to \0 (which is appended to the end of strings created using char* a.k.a String literals)
Check this too.
That is because you those strings are actually arrays of characters. What you do with the line char *name = "xxxxx";: You construct an array of 6 character values (5 of them being 'x' and the last one being '\0'). name is a pointer to that array.
That's how strings are normally handles in C, you have some kind of sequence of characters, terminated with a '\0' character, to tell functions like printf where to stop processing the string.
Let's consider this piece of code:
char *name="xxxxx";
What happens here is that the string xxxxx is allocated memory and a pointer to that memory location,or the address of that string is passed to the pointer variable name.Or in other words you initialize name with that address.
And printf() is a variadic function (one that takes one fixed argument followed by a random number of arguments).The first argument to printf() is of type const char*.And the string identifier name when passed as an argument denotes the base address of that string.Hence you can use
printf(name);
It will simply output xxxxx
name=&name too. How can it be?--Well that's a justified question.
Let me explain first with a real-world analogy. Suppose you have the first house in a row of houses in a housing society.Suppose it's plot number 0.The other houses are on plots 1,2,3......Now suppose there is a pointer to your house, and there is another pointer to the whole housing society's row. Won't the two pointers have the same address, which will be plot 0?This is because a pointer signifies a single memory location.It's the type of the pointer that matters here.
Bringing this analogy to the string( array of characters), the name identifier only signifies the base address of the string, the address of its first character (Like the address of the first house).It is numerically same to the address of the whole string,which is (&name),which in my analogy is the ROW of houses.But they are of different types, one is of type char* and the other is of type char**.
Basicly what happens when the C-compiler see the expression
char *name = "xxxxx";
is, it will say. Hey "xxxxx" that's a constant string (which is an array of bytes terminated with a 0 byte), and put that in the resulting programs binary. Then it will substitute the string for the memory location, sort of like:
char *name = _some_secret_name_the_compiler_only_know;
where _some_secret_name_the_compiler_only_know is a pointer to the memory location where the string will live once the program gets executed. And get in with parsing the file.