I just started learning the relationship between pointers and arrays. What I read from this thread(What is the difference between char a[] = ?string?; and char *p = ?string?;?) is the string pointed by the pointer can not be changed. But in the following piece of code, I can change the string pointed by pa from abc to abd without any problem.
int main()
{
char *pa;
pa="abc";
cout<<pa<<endl<<endl;
pa="abd";
cout<<pa<<endl<<endl;
return 0;
}
However, it does not work in this piece of code. Can someone explain the difference to me? Thank you very much!!
int main()
{
char *pc;
pc="abc";
cout<<pc<<endl<<endl;
*(pc+2)='d';
cout<<pc<<endl<<endl;
return 0;
}
In the first case you are not changing the string, actually, what is happening is first you were pointing to "abc" (pa="abc";) then you are making the pointer to point to "abd" (pa="abd";), the previous string i.e."abc" remains unchanged in the memory.
And in the second case your pc pointer is pointing to the same string, and the statement *(pc+2) = d tries to modify the value pointed by pc, which cannot be done.
#user3858 I don't know whether you are aware of static,automatic and dynamic memory allocations or not but let me tell you that 'pa' is your automatic (pointer) variable initially pointing to a static memory region "abc" and which you later shifted it to point to some other memory region filled with "abd"."abc" and "abd" ,both are separate regions.And in your second program you are actually making a change in the "abc" region to make it "abd" and for which you are encountering an error.
Normally, string literals are stored in read-only memory when the program is running. This is to prevent you from accidentally changing a string constant. That's what happened in the second example, i.e. you will get a segmentation fault error.
This didn't happen in your first example because you are not changing the string itself. Instead, you just changed char *pa from pointing to one string to another.
You may need to check out: Why do I get a segmentation fault when writing to a string initialized with "char *s" but not "char s[]"?
P.S. I recommend you to use string if you do need to change some part of it.
string pc = "abc";
pc[2] = 'd';
Here, read-only "abc" is copied into non-const pc to enable you to change its content.
Related
I read this on wikipedia
int main(void)
{
char *s = "hello world";
*s = 'H';
}
When the program containing this code is compiled, the string "hello world" is placed in the section of the program executable file marked as read-only; when loaded, the operating system places it with other strings and constant data in a read-only segment of memory. When executed, a variable, s, is set to point to the string's location, and an attempt is made to write an H character through the variable into the memory, causing a segmentation fault**
i don't know why the string is placed in read only segment.please someone could explain this.
String literals are stored in read-only memory, that's just how it works. Your code uses a pointer initialized to point at the memory where a string literal is stored, and thus you can't validly modify that memory.
To get a string in modifiable memory, do this:
char s[] = "hello world";
then you're fine, since now you're just using the constant string to initialize a non-constant array.
There is a big difference between:
char * s = "Hello world";
and
char s[] = "Hello world";
In the first case, s is a pointer to something that you can't change. It's stored in read-only memory (typically, in the code section of your application).
In the latter case, you allocate an array in read-write memory (typically plain RAM), that you can modify.
When you do: char *s = "hello world"; then s is a pointer that points to a memory that is in the code part, so you can't change it.
When you do: char s[] = "Hello World"; then s is an array of chars
that are on the stack, so you can change it.
If you don't want the string to be changed during the program, it is better to do: char
const *s = ....;. Then, when you try to change the string, your program will not crash with segmentation fault, it will arise a compiler error (which is much better).
first have a good understanding of pointers, I will give u a short demo:
First let us analyze your code line by line. Lets start from main onwards
char *s = "Some_string";
first of all, you are declaring a pointer to a char variable, now *s is a address in memory, and C will kick you if you try to change its memory value, thats illegal, so u better declare a character array, then assign s to its address, then change s.
Hope you get, it. For further reference and detailed understanding, refer KN King: C programming A Modern Approach
Per the language definition, string literals have to be stored in such a way that their lifetime extends over the lifetime of the program, and that they are visible over the entire program.
Exactly what this means in terms of where the string gets stored is up to the implementation; the language definition does not mandate that string literals are stored in read-only memory, and not all implementations do so. It only says that attempting to modify the contents of a string literal results in undefined behavior, meaning the implementation is free to do whatever it wants.
1a) There is this code
char *p;
p[0]='a';
p[1]='b';
printf("%s",p);
When i run this program on ideone.com compiler: c++ 4.3.2, it displays "RUNTIME ERROR" every single time i run it.
1b). however when i edit this code to
char *p;
//allocate memory using malloc
p[0]='a';
p[1]='b';
printf("%s",p);
It correctly runs and prints "ab" . shouldn't it require the p[2]='\0' at the end?
2)
char *p;
p="abc"
printf("%s",p);
this correctly runs and prints "abc" . why does this work without allocation.
Can anyone please explain the rules regarding string storage ?
1a) undefined behavior because you dereference a non initialized pointer
1b) undefined behavior since you call printf with %s for a non null terminated string
2) works ok: there is an allocation, it just is a string literal (you can't modify it, it is stored in the read-only portion of the program : you should declare it const char* for that reason)
Note:
In C++, use std::string and std::cout .
In the first example you declare a pointer to char and then you assign values to undefined locations in memory. Undefined because its what the uninitialize p pointer points to. You need to allocate memory for the sequence (with new[] in C++, not malloc). If you do not put a '\0' at the end, printing will stop at the first 0 encountered in memory.
In the third example you are declaring a pointer to char and initialize its value with the address of the literal string "abc". That is stored in the (read-only) data section in the executable and that gets map to the process address space. So that's a valid pointer and your printing works.
1a) here you don't allocate memory, so the p pointer points to a random place, therefore causing segfault when you write that random location
1b) if you allocate memory manually with malloc, it will work correctly. If the allocated memory contains 0s, you don't have to add it manually (but you should, because you can't count on the zero filling)
2) here you assign the p pointer to the string literal "abs", so it will point to it, and the allocation is done by the compiler
I'm new to C++ and I'm playing with pointers. I can't figure out why this piece of code doesn't work for me. Can you tell me what's wrong with it?
char * name = "dharman";
char *ptr = name+3;
*ptr = 'a';
printf("%s", name);
I get unhandled exception all the time.
This alone is an error:
char * name = "dharman";
The string is in constant memory but the pointer's type indicates it can be modified. Attempting to modify it produces undefined behavior: on other platforms the program will work but you got unlucky.
This was a quirk in C++03; the newer C++11 spec makes it illegal. The reason it was ever done was C compatibility.
Whether you're writing in C++ or plain C, the solution is simple:
char name[] = "dharman";
Now the compiler stores the data in read-write memory because you have asked for an array of char, not a pointer to some other memory.
String literals, like "dharman", are read-only and you cannot modify them. Instead, create and initialize an array that is not read only.
char name[] = "dharman";
name is a pointer to a string literal "dharman", which is located in read-only memory.
In your statement *ptr = 'a', you are trying to modify this string literal, which results in Undefined Behavior
It doesn't work because "dharman" is constant, it's a string literal. You cannont change it!
String literals are usually placed in read-only segments of memory.
You are trying to modify a constant string.
You need to copy the constant first to some memory that you own.
Try this:
char *name = (char*) malloc(10);
memcpy(name, "dharman", strlen("dharman"));
...
You are setting name to point at a const string and then trying to modify it. Copy the string to a modifiable location:
char *name = (char*) malloc(strlen("dharman") + 1);
memcpy("dharman", name, strlen("dharman") + 1);
The reason for unhandled exception in your case is.In your code
char *ptr= name+3;
consider the base address of name as eg:23300, so char *ptr =name+3 will be equal to
23300+(3*sizeof(char)).so now ptr points to 23300+(3*1)=23303.each element occupies one bye for char so ptr will point to letter 'a' in "dharman".since "dharman" is char const you can't its value that's why you are getting error.if u remove the line *ptr=3.the code will work without out any issue.I hope you find this post useful.
While running following code, my program crashes unexpectedly!
#include<stdio.h>
#include<string.h>
int main(){
char *str = NULL;
strcpy(str, "swami");
printf("%s", str);
return 0;
}
But if I do like this:
#include<stdio.h>
#include<string.h>
int main(){
char *str;
strcpy(str, "swami");
printf("%s", str);
return 0;
}
This code works fine and generates correct output!
I am using gcc compiler(codeblocks IDE). Also, both the codes lead to program crash in DevCpp. Can anyone please explain me why this is so!?
You cannot write to NULL pointers.
In the second case, it happened that your pointer was randomly initialized to a valid location in your program's memory. That is why you could do a strcpy into it.
Change both programs to have
str = malloc(size)
or the option with calloc before the strcpy. (size is the size of the space you want to reserve.)
As per comment, you can also change the declaration of str to be char str[6] (or more).
Last edit: I'll present you this picture showing the memory of your program and the pointers:
The gray areas and the red one are forbidden (you cannot write or read from them; the top gray one is for kernel memory while the others are spaces not yet reclaimed). The red area at the bottom is the special 0 page. Since NULL is 0 your str = NULL will point to this and your program will fail.
If you don't assign anything to str it will end up pointing randomly. It can still point to the red area or to a grey area -> your program will fail. It could point to a green or blue (both hues) area, making your program work (excepting the cases where it is pointing to a read-only location and you write to it). Allocating area for the pointer makes it point to the green area, enlarging it to the top.
The other option, with str[6] enlarges the stack area to bottom. All local variables have space reserved into the stack while all space allocated with malloc, realloc, calloc and other friends goes into the heap.
Lastly, have a look at a blog article about the difference between char[] and char *.
PS: If you'd want to use a GNU extension you can look into the asprintf function. It would allocate space for a string and write some content there:
asprintf(&str, "swami");
or
asprintf(&str, "%d + %d == %d\n", 1, 2, 3);
But, if you want portability, you'd stay away from this function.
In neither version have you allocated memory to copy the string to, so both invoke undefined behaviour. The first one crashes because you explicitly initialised str to NULL, so the strcpy dereferences a NULL pointer, that crashes on most systems. In the second, str points to arbitrary memory, dereferencing that uninitialised pointer may or may not crash.
Because NULL is #define NULL ((void *)0) in <stdlib.h>. So, you try to write in invalid memory address that make your program crash.
Read this link
//destination =Pointer to the destination array where the content is to be copied.
char * strcpy ( char * destination, const char * source );
You're setting destination to NULL, so you're trying to copy source to NULL. That's why it crashes. You should be setting some memory asside to copy the string to instead.
int main(){
char *str=malloc(6); //enough for "swami"+'\0'
strcpy(str, "swami");
printf("%s", str);
return 0;
}
strcpy just copies, not generating space for it.
in the first case you tried to write the string to the beginning of the code segment: not a good idea.
in the second case, you started writing the string to somewhere, and in your case didn't crash do to luck and maybe compiler help.
you should do one of the following:
a. allocate memory: str = new char[10]
b. use strdup witch well duplicate the string into a new location.
may be this is a sizzle question but please help
void Temp1::caller()
{
char *cc=Called();
printf("sdfasfasfas");
printf("%s",cc);
}
char *Temp1::Called()
{
char a[6]="Hello";
return &a;
}
Here how to print Hello using printf("%s",cc);
Firstly, this function:
char *Temp1::Called()
{
char a[6]="Hello";
return &a;
}
is returning a local variable, which will cease to exist once the function ends - change to:
const char *Temp1::Called()
{
return "Hello";
}
and then, the way to print strings using printf() is to use "%s":
void Temp1::caller()
{
const char *cc=Called();
printf("sdfasfasfas");
printf("%s",cc);
}
You are returning address of local variable, which exploits undefined behaviour. You need to make a static inside Called, or global, or allocate memory for it.
And use %s as format for printf
char a[6] is a local variable and you can not return it from function. It will be destroyed when your code will go out of scope.
You can use STL fot this:
#include <stdio.h>
#include <string>
using namespace std;
string Called()
{
string a=string("Hello");
return a;
}
int main()
{
string cc=Called();
printf("sdfasfasfas\n");
printf("%s",cc.c_str());
}
2 things
You need %s, the string format specifier to print strings.
You are returning the address of a local array variable a[6], it will be destroyed after the function returns. The program should be giving you a segmentation fault. You should be getting a crash. If you are on a linux machine do ulimit -c unlimited, and then run the program. You should see a core dump.
%c is for printing a single character. You need to use %s for printing a null terminated string. That said, this code is likely to crash as you are trying to return the address of the local variable a from function Called. This variable memory is released as soon as Called is returned. You are trying to use this released memory is Caller and in most of the cases it will crash.
Few things:
Change return &a; to return a;
You are returning the address of a
local array which will cease to exist
once the function return..so allocate
it dynamically using new or make it static.
use %s format specifier in printf in place of %c
Problem 1: %c is the specifier for a single char, while you need to use %s, which is the format specifier for strings (pointers to a NUL-terminated array of chars).
Problem 2: in Called you are returning a pointer to a pointer to char (a char **): a itself is considered a pointer to the first element of the array, so you don't need that ampersand in the return.
Problem 3: even if you corrected the other two errors, there's a major flaw in your code: you're trying to return a pointer to a local object (the array a ), which will be destructed when it will get out of scope (e.g. when Called will return). So the caller will have a pointer to an area of memory which is no longer dedicated to a; what happens next is undefined behavior: it may work for a while, until the memory where a was stored isn't used for something else (for example if you don't call other functions before using the returned value), but most likely will explode tragically at the first change in the application.
The correct method for returning strings in C is allocating them on the heap with malloc or calloc and return this pointer to the caller, which will have the responsibility to free it when it won't be needed anymore. Another common way to do it in C is to declare the local variable as static, so it won't be destructed at the return, but this will make your function non-reentrant neither thread-safe (and it may also give other nasty problems).
On the other hand, since you are using C++, the best way to deal with strings is the std::string class, which has a nice copy semantic so that you can return it as a normal return value without bothering about scope considerations.
By the way, if the string you need to return is always the same, you can just declare the return type of your function as const char * and return directly the string, as in
const char * Test()
{
return "Test";
}
This works because the string "Test" is put by the compiler in a fixed memory location, where it will stay during all the execution. It needs to be a const char * because the compiler is allowed to say to every other piece of program that needs a "Test" string to look there, and because all the strings of the application are tightly-packed there, so if you tried to make that string longer you would overwrite some other string.
Still, in my opinion, if you are doing errors like those I outlined, it may be that you're trying to do something a bit too complex for your current skills: if may be better to have another look at your C++ manual, especially at the chapter about pointers and strings.