Error in string initialisation - c

Here I was trying out the following thing in my code and got the following error---"prog.c:10:8: error: incompatible types when assigning to type ‘char[100]’ from type ‘char *’". Please help and tell me how can I modify my initialisation which is char str[100] to get the right answer
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[100];
str = "a";
str = str + 1;
str = "b";
str = str + 1;
str = "c";
str = str + 1;
printf("%s", str - 2);
return 0;
}

You have declared an array
char str[100];
By specifying the name of the array you will get the base address of the array which is same as the address of first element.
str="a";
In the above statement, you are trying to assign "a"s (note "a" is string here) address to array base.
The compiler will not allow you to do this. Cos, if you do so, you will lose all the 100 elements.
If you want to assign the first element with the value 'a', then do
str[0] = 'a';
Note that I have used single quote. Remember "Single quote for single char".

You have to use string commands like strcpy/strncpy.
Or you can allocate memory to accomodate the string and use only char pointers, no char array.

while arrays and pointers are closely related in C, they are not entirely the same.
char str[100];
gives you a "const pointer"-like handle to a pre-allocated array of 100 chars. this array will live at a fixed position in memory, so you cannot let str point to some other place.
str="a";
will assign the position of a string "a" to the pointer "str". (which is illegal!).
what you can do, is to assign the values within your array.
char str[100] = {0};
str[0]='a';
str[1]='b';
str[2]='c';
printf("%s", str);

treat str as an array and not as a pointer (str points to a memory address allocated for 100 chars and str[i] accesses the relative memory address of str + i)
char str[100];
str[0]='a';
str[1]='b';
str[2]='c';
str[3]='\0';
printf("%s",str);

if want initialisation a str[100],use this:
char str[100] = "abc";
it only work when we define the str[100] and initialisation str[100] at the same time!
Or you code can work in this way:
char str[100];
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
str[3] = '\0';
Or :
char str[100];
*str = 'a';
++str;
*str = 'b';
++str;
*str = 'c';
++str;
*str = '\0';

In general when you create an array of characters like this.
char string[100]; //allocate contigious location for 100 characters at compile time
Here string will point to the base address of the contigious location. Assuming memory address starts from 4000 then it would be like
--------------------------------------
|4000|4001|4002|4003|...........|4099|
--------------------------------------
Variable string will point to 4000. To store a value at 4000 you can do *(4000).
Here you can do like
*string='a'; //4000 holds 'a'
*(string+1)='b'; //4001 holds 'b'
*(string+2)='c'; //4002 holds 'c'
Note: Array can be accessed by any of the three forms in c.
string[0] => 0[string] => *(string+0) => points to first element in string array
where
string[0] => *(4000+0(sizeof(char))) => *(4000)
0[string] => *((0*sizeof(char))+4000) => *(4000)
*string => *(4000)
In case of integer array, assuming int takes 4bytes of memory
int count[100]; //allocate contigious location for 100 integers at compile time
Here count will point to the base address of the contigious location. Assuming memory address starts from 4000 then it would be like
--------------------------------------
|4000|4004|4008|4012|...........|4396|
--------------------------------------
variable count will point to 4000. To store a value at 4000 you can do *(4000).
Here you can do like
*count=0; //4000 holds 0
*(count+1)=1; //4004 holds 1
*(count+2)=2; //4008 holds 2
So coming to your code, your objective can be achieved like this.
#include<stdio.h>
#include<stdlib.h>
int main()
{
char str[100];
*str='a';
*(str+1)='b';
*(str+2)='c';
printf("%s",str);
return 0;
}
Output: abc

You persist in using the wrong term, which leads me to believe that is why you couldn't find an answer.
/* 1 */
char str[100] = "a"; //OK
/* 2 */
str = "b"; // error: str is an array
Initialization is what happens when you assign a value to a variable while declaring the variable. This is source code excerpt 1 above.
Assignment is what happens after the variable is declared. You can't assign to a struct or array type. You must address each individual item in the struct/array when assigning values. In code excerpt 2 above, the variable str is assigned the value "b", except that str is an array, so the compiler says there is an error because you can't assign to an array.
Summary:
You can initialize an array, but you cannot assign to it. The difference is in whether the variable was given an explicit value when it was declared. If it was, the variable was initialized. Otherwise, you're trying to assign to an array, which can't be done.

Many, even I when learning c, was confused like you.
Actually you must be clear on this
Difference between `char []` and `char *`
=>char [] is a constant pointer which refers to the same address every time. But its value is not constant
=>char * is a non-constant pointer which can be changed to refer to any string. Its value is also not constant, but if it is assigned the address of a const char * then its value will be const.
Coming to your question
Use methods instring.h
#include<stdio.h>
#include<stdlib.h>
int main()
{
char string[100];
char *str;
*str = 'a';
str = str + 1;
*str = 'b';
str = str + 1;
*str = 'c';
str = str + 1;
printf("%s", str - 2);
return 0;
}

Related

How do I access individual char's in an array of char pointers? [duplicate]

I have a string,
char* str = "HELLO"
If I wanted to get just the E from that how would I do that?
char* str = "HELLO";
char c = str[1];
Keep in mind that arrays and strings in C begin indexing at 0 rather than 1, so "H" is str[0], "E" is str[1], the first "L" is str[2] and so on.
You would do:
char c = str[1];
Or even:
char c = "Hello"[1];
edit: updated to find the "E".
Array notation and pointer arithmetic can be used interchangeably in C/C++ (this is not true for ALL the cases but by the time you get there, you will find the cases yourself). So although str is a pointer, you can use it as if it were an array like so:
char char_E = str[1];
char char_L1 = str[2];
char char_O = str[4];
...and so on. What you could also do is "add" 1 to the value of the pointer to a character str which will then point to the second character in the string. Then you can simply do:
str = str + 1; // makes it point to 'E' now
char myChar = *str;
I hope this helps.

How to set a char 'a' to a char pointer array?

I'm trying to figure out how to use pointers.
I'm confused on how to insert an individual char to the char *line2[80]
Is this even possible to do this without referencing the memory location of another pointer?
My thought process is that at *line2[0] = 'a' the character 'a' will be at index 0 of the array.
How is this different from line[0] = 'a'
#include <stdio.h>
void returnValue(void);
int main(void){
returnValue();
}
void returnValue(){
char line[80];
line[0] = 'a';
line[1] = '\0';
printf("%s",line);
char* line2[80];
*line2[0] = 'a';
*line2[1] = '\0';
printf("%s",*line2); //program crashes
}
When you allocate
char* line2[80];
You are allocating an array of 80 character pointers.
When you use
*line2[0] = 'a';
You are referencing undefined behaviour. This is because you are allocating the pointer line2[0], but the pointer is not initialized and may not be pointing to any valid location in memory.
You need to initialize the pointer to some valid location in memory for this to work. The typical way to do this would be to use malloc
line2[0] = malloc(10); // Here 10 is the maximum size of the string you want to store
*line2[0] = 'a';
*(line2[0]+1) = '\0';
printf("%s",*line2);
What you are doing in the above program is allocating a 2D array of C strings. line2[0] is the 1st string. Likewise, you can have 79 more strings allocated.
you must have already read, a pointer is a special variable in c which stores address of another variable of same datatype.
for eg:-
char a_character_var = 'M';
char * a_character_pointer = &a_character_var; //here `*` signifies `a_character_pointer` is a `pointer` to `char datatype` i.e. it can store an address of a `char`acter variable
likewise in your example
char* line2[80]; is an array of 80 char pointer
usage
line2[0] = &line[0];
and you may access it by writing *line2[0] which will yield a as output

Run-time error in program

int main()
{
char *p="abcd";
while(*p!='\0') ++*p++;
printf("%s",p);
return 0;
}
I am not able to understand why the code does not run. The problem is in the statement ++*p++, but what is the problem?
P points to constant string literal *p="abcd"; by doing ++*p++ you are trying to modify string '"abcd"', for example a in string will be increment to 'b' because of ++*p that is undefined behavior (constant string can't change). it may cause a segmentation fault.
`++*p++` means `++*p` then `p++`
^
| this operation try to modify string constant
char *p="abcd";
p is pointing to a readonly segment and you can not increment p as you did here
while(*p!='\0') ++*p++;
//char *p="abcd";//"string" is const char, don't change.
char str[]="abcd";//is copied, including the '\0' to reserve space
char *p = str;
while(*p!='\0') ++*p++;
//printf("%s",p);//address pointing of 'p' has been changed
printf("%s",str);//display "bcde"
char *foo = "abcd";
char bar[] = "abcd";
Consider the differences between foo and bar. foo is a pointer that's initialised to point to memory reserved for a string literal. bar is an array with it's own memory that's initialised to a string literal; it's value is copied from the string literal during initialisation. It is appropriate to modify bar[0], etc, but not foo[0]. Hence, you need an array declaration.
However, you can't increment an array declaration; That's an operation for pointer variables or integer variables. Additionally, your loop changes where p points at, before it's printed, so you need to keep the original location of your string somewhere. Hence, you also need a pointer, or an integer declaration.
With this in mind, it might seem like a good idea to change your code to something like this:
int main()
{
char str[] = "abcd";
/* Using a pointer variable: */
for (char *ptr = str; *ptr != '\0'; ++*ptr++);
/* Using a size_t variable: */
for (size_t x = 0; str[x] != '\0'; str[x++]++);
printf("%s", str);
return 0;
}

Initializing arrays of type char

I want to initialize arbitrary large strings. It is null terminated string of characters, but I cannot print its content.
Can anybody tell me why?
char* b;
char c;
b = &c;
*b = 'm';
*(b+1) = 'o';
*(b+2) = 'j';
*(b+3) = 'a';
*(b+4) = '\0';
printf("%s\n", *b);
Your solution invokes undefined behaviour, because *(b+1) etc. are outside the bounds of the stack variable c. So when you write to them, you're writing all over memory that you don't own, which can cause all sorts of corruption. Also, you need to printf("%s\n", b) (printf expects a pointer for %s).
The solution depends on what you want to do. You can initialize a pointer to a string literal:
const char *str1 = "moja";
You can initialize a character array:
char str2[] = "moja";
This can also be written as:
char str2[] = { 'm', 'o', 'j', 'a', '\0' };
Or you can manually assign the values of your string:
char *str3 = malloc(5);
str3[0] = 'm';
str3[1] = 'o';
str3[2] = 'j';
str3[3] = 'a';
str3[4] = '\0';
...
free(str3);
This might result in a segmentation fault! *(b+1), *(b+2) etc refer to unallocated areas. First allocate memory and then write into it!
b doesn't have enough space to hold all those characters. Allocate enough space using malloc or declare b as a char array.
Your code is not safe at all! You allocate only 1 char on the stack with char c; but write 5 chars into it! this will give you a stack-overflow which can be very dangerous.
Another thing: you mustn't dereference the string when printing it: printf("%s\n", b);
Why not simply write const char *b = "mojo";?
You need to assign memory space for it, either with malloc or using a static array. Here, in your code, you're using the address of just one character to store at the addresses of that characters, and others following it. This is not defined.
Note, step by step, what you're doing. First, you assign the pointer to point to a single char space in memory. Then, by using *b = 'm' you set that memory to the character 'm'. But then, you access to the next memory position (that is undefined, because no memory is reserved for that position) to store another value. This won't work.
How to do it?
You have two options. For example:
char *b;
char c[5];
b = &c[0];
*b = 'm';
... //rest of your code
This will work because you have space for 5 chars in c. The other option is to directly assign memory for b using malloc:
char * b = (char*) malloc(5);
*b = 'm';
... // rest of your code
Finally, maybe not what you want, but you can either initialize a char array or pointer using a string literal:
char c[] = "hello";
const char* b = "abcdef";
The printf does not print because it expect a char*, so you should pass b, not *b.
To initialize a pointer to a string constant you can do something like:
char *s1 = "A string"
or
char s2[] = "Another string"
or allocate a buffer with char *b = malloc(5) and then write to this buffer (as you did, or with the string functions)
what you did was taking the address of a single char memory location and then write past to it, possibly overwriting other variables or instructions and thus possibly leading to data corruption or crash.
If you write the following instead of your printf, it will print the first character.
printf("%c\n", *b);
In order for you to have arbitrarily large strings, you will need to use a library such as bstring or write one of your own.
This is because, in C one needs to get memory, use it and free it accordingly. b in your case only points to a character unless you allocate memory to it using malloc. And for malloc you have to specify a fixed size.
For arbitrarily large string, you need to encapsulate the actual pointer to character in a data structure of your own, and then manage its size according to the length of the string that is to be set as its value.
printf("%s\n", *b);
why *?
printf("%s\n", b);
is what you want

Why does *(str+i) = *(str +j) not work here?

void reverse(char *str){
int i,j;
char temp;
for(i=0,j=strlen(str)-1; i<j; i++, j--){
temp = *(str + i);
*(str + i) = *(str + j);
*(str + j) = temp;
printf("%c",*(str + j));
}
}
int main (int argc, char const *argv[])
{
char *str = "Shiv";
reverse(str);
printf("%s",str);
return 0;
}
When I use char *str = "Shiv" the lines in the swapping part of my reverse function i.e str[i]=str[j] dont seem to work, however if I declare str as char str[] = "Shiv", the swapping part works? What is the reason for this. I was a bit puzzled by the behavior, I kept getting the message "Bus error" when I tried to run the program.
When you use char *str = "Shiv";, you don't own the memory pointed to, and you're not allowed to write to it. The actual bytes for the string could be a constant inside the program's code.
When you use char str[] = "Shiv";, the 4(+1) char bytes and the array itself are on your stack, and you're allowed to write to them as much as you please.
The char *str = "Shiv" gets a pointer to a string constant, which may be loaded into a protected area of memory (e.g. part of the executable code) that is read only.
char *str = "Shiv";
This should be :
const char *str = "Shiv";
And now you'll have an error ;)
Try
int main (int argc, char const *argv[])
{
char *str = malloc(5*sizeof(char)); //4 chars + '\0'
strcpy(str,"Shiv");
reverse(str);
printf("%s",str);
free(str); //Not needed for such a small example, but to illustrate
return 0;
}
instead. That will get you read/write memory when using pointers. Using [] notation allocates space in the stack directly, but using const pointers doesn't.
String literals are non-modifiable objects in both C and C++. An attempt to modify a string literal always results in undefined behavior. This is exactly what you observe when you get your "Bus error" with
char *str = "Shiv";
variant. In this case your 'reverse' function will make an attempt to modify a string literal. Thus, the behavior is undefined.
The
char str[] = "Shiv";
variant will create a copy of the string literal in a modifiable array 'str', and then 'reverse' will operate on that copy. This will work fine.
P.S. Don't create non-const-qualified pointers to string literals. You first variant should have been
const char *str = "Shiv";
(note the extra 'const').
String literals (your "Shiv") are not modifiable.
You assign to a pointer the address of such a string literal, then you try to change the contents of the string literal by dereferencing the pointer value. That's a big NO-NO.
Declare str as an array instead:
char str[] = "Shiv";
This creates str as an array of 5 characters and copies the characters 'S', 'h', 'i', 'v' and '\0' to str[0], str[1], ..., str[4]. The values in each element of str are modifiable.
When I want to use a pointer to a string literal, I usually declare it const. That way, the compiler can help me by issuing a message when my code wants to change the contents of a string literal
const char *str = "Shiv";
Imagine you could do the same with integers.
/* Just having fun, this is not C! */
int *ptr = &5; /* address of 5 */
*ptr = 42; /* change 5 to 42 */
printf("5 + 1 is %d\n", *(&5) + 1); /* 6? or 43? :) */
Quote from the Standard:
6.4.5 String literals
...
6 ... If the program attempts to modify such an array [a string literal], the behavior is undefined.
char *str is a pointer / reference to a block of characters (the string). But its sitting somewhere in a block of memory so you cannot just assign it like that.
Interesting that I've never noticed this. I was able to replicate this condition in VS2008 C++.
Typically, it is a bad idea to do in-place modification of constants.
In any case, this post explains this situation pretty clearly.
The first (char[]) is local data you can edit
(since the array is local data).
The second (char *) is a local pointer to
global, static (constant) data. You
are not allowed to modify constant
data.
If you have GNU C, you can compile
with -fwritable-strings to keep the
global string from being made
constant, but this is not recommended.

Resources