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

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

Related

Error in string initialisation

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

How does strcpy() copy a string to an array when you can't change the address of an array?

So basically strcpy assigns the address of the 2nd argument to the 1st, but how does it do it with an array as the first argument? like in my program, i tried changing the address of the array but unfortunately it wont compile. So I had to resort to making a character pointer variable to assign the return value of capitalize. Is there something I'm misunderstanding?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char string[20];
char *Capitalize(char *str)
{
int i;
char *temp;
temp = malloc(sizeof(char)*(int)(strlen(str)+1));
for(i = 0;i < strlen(str);i++)
{
if(*(str+i) >= 'a' && *(str+i)<= 'z')
*(temp+i) = *(str+i) - 32;
else
*(temp+i) = *(str+i);
}
*(temp+i) = '\0';
return temp;
}
int main(void)
{
string word;
printf("Enter word to capitalize: ");
scanf("%19s",word);
word = Capitalize(word);
printf("%s",word);
return 0;
}
strcpy() makes a copy, just like the name implies. it's perfectly legal to copy a string in to an array.
When you make an initialization of an array such as:
char myarr[] = "hello";
You're actually copying the characters into the array.
You seem to be confusing arrays with pointers (see here for some reason you can't treat them the same)
In C, qualifying an array by name without an indexer, is equivalent to specifying a pointer to the memory address of the first element in the array, that is why you can pass as a parameter an array to functions like strcpy.
char * strcpy ( char * destination, const char * source );
strcpy will copy whatever series of characters are found, starting at memory address specified by source, to the memory address specified by destination, until a null character (0) is found (this null character is also copied to the destination buffer).
The address values specified in the parameters are not modified, they just specify from where in memory to copy and where to. It is important that destination is pointing to a memory buffer (can be a char array or a block of memory requested via malloc) with enough capacity for the copied string to fit, otherwise a buffer underrun will occur (you will write characters past the end of your buffer) and your program might crash or behave in a weird way.
Hope I have been clear and not confused you more with my explanation ;)
The thing you seem to be missing is that in c/c++ strings ARE arrays, in most practical respects declaring
char c[] = "hello";
and
char* c = "hello";
is the same thing, all strcpy does is copy the characters into the destination memory, whether that memory is allocated as an array (presumably on the stack) or pointer (presumably on the heap);it does not make a difference.

Cannot assign char to char pointer

Here is my code:
printf("%s\n", "test1");
char c = '2';
char * lines[2];
char * tmp1 = lines[0];
*tmp1 = c;
printf("%s\n", "test2");
I don't see the second printf in console.
Question: Can anybody explain me what's wrong with my code?
NOTE: I'm trying to learn C :)
This line:
char * lines[2];
declares an array of two char pointers. However, you don't actually initialize the pointers to anything. So later when you do *tmp1 = (char)c; then you assign the character c to somewhere in memory, possibly even address zero (i.e. NULL) which is a bad thing.
The solution is to either create the array as an array of arrays, like
char lines[2][30];
This declares lines to have two arrays of 30 characters each, and since strings needs a special terminator character you can have string of up to 29 characters in them.
The second solution is to dynamically allocate memory for the strings:
char *lines[2];
lines[0] = malloc(30);
lines[1] = malloc(30);
Essentially this does the same as the above array-of-arrays declaration, but allocates the memory on the heap.
Of course, maybe you just wanted a single string of a single character (plus the terminator), then you were almost right, just remove the asterisk:
char line[2]; /* Array of two characters, or a string of length one */
The array lines in uninitialized. Thus lines[0] is an uninitalized pointer. Dereferencing it in *tmp1 is sheer undefined behaviour.
Here's an alternative, that may or may not correspond to what you want:
char lines[2];
char * tmp1 = lines; // or "&lines[0]"
*tmp = c;
Or, more easily:
char lines[2] = { c, 0 };
lines is uninitialized, and tmp1 initialization is wrong.
It should be:
char lines[2];
char * tmp1 = lines;
Alternatively, you can say:
char * tmp1 = &lines[0];
Or else for an array of strings:
char lines[2][30];
char * tmp1 = lines[0];
The line
char * lines[2];
creates an array of two char pointers. But that doesn't allocate memory, it's just a "handle" or "name" for the pointer in memory. The pointer doesn't point to something useful.
You will either have to allocate memory using malloc():
char * lines = malloc(2);
or tell the compiler to allocate memory for you:
char lines[2];
Note: Don't forget to terminate the string with a 0 byte before you use it.
char *lines[2]; : A two element array of char pointers.
char *tmp; : A pointer to a character.
char *tmp = lines[0] : The value inside the array element 0 of the lines array is transferred into tmp. Because it is an automatic array, therefore it will have garbage as the value for lines[0].
*temp : Dereference the garbage value. Undefined Behaviour.
char * tmp1 = lines[0];
here you declare a char pointer and initialize its pointer value to line[0],the fist element stored in line array which is also uninitialized.
now the tmp is pointing to somewhere unknown and not actually accessible. When you
*tmp1 = (char)c;
you are operating on a invalid memory address which causes a Segmentation fault.

Dereferencing a double pointer and using index operator

I am passing a double pointer of type char ** to a function. Inside that function, I need to dereference the pointer and then index through the character array.
Unfortunately, I am getting a core dump when I try to assign a capital letter back into the array.
I need help on how to do this. (This is not homework, just a personal project.)
void buffer(char **ppline);
int main()
{
char *line="The redcoats are coming!";
buffer(&line);
printf("\nline = %s\n",line);
return(0);
}
void buffer (char **ppline)
{
int i=0;
char a;
for (i=0; i < strlen(*ppline); i++)
{
a = toupper( (*ppline)[i] ); /* THIS LINE CAUSES THE CORE DUMP */
((*ppline)[i]) = a;
}
return;
}
A string literal in "" is constant. You cannot modify it as you're doing, as that is undefined behavior. Try this, which allocates storage and copies the string literal into it:
void buffer(char **ppline);
int main()
{
char line[] = "The redcoats are coming!";
buffer(&line);
printf("\nline = %s\n",line);
return(0);
}
void buffer (char **ppline)
{
int i=0;
char a;
for (i=0; i < strlen(*ppline); i++)
{
a = toupper( (*ppline)[i] ); /* THIS LINE CAUSES THE CORE DUMP */
((*ppline)[i]) = a;
}
return;
}
Stack, heap, datasegment(and BSS) and text segement are the four segments of process memory. All the local variables defined will be in stack. Dynmically allocated memory using malloc and calloc will be in heap. All the global and static variables will be in data segment. Text segment will have the assembly code of the program and some constants.
In these 4 segements, text segment is the READ ONLY segment and in the all the other three is for READ and WRITE.
char []a="The redcoats are coming!"; - This statemnt will allocate memory for 25 bytes in stack(because local variable) and it will keep all the 24 characters plus NULL character (\0) at the end.
char *p="The redcoats are coming!"; - This statement will allocate memory for 4 bytes(if it is 32 bit machine) in stack(because this is also a local variable) and it will hold the pointer of the constant string which value is "The redcoats are coming!". This byte of constant string will be in text segment. This is a constant value. Pointer variable p just points to that string.
Now a[0] (index can be 0 to 24) means, it will access first character of that string which is in stack. So we can do write also at this position. a[0] = 'x' This operation is allowed because we have READ WRITE access in stack.
But p[0] = 'x' will leads to crash, because we have only READ access to text segement. Segmentation fault will happen if we do any write on text segment.
But you can change the value of variable p, because its local variable in stack. like below
char *p = "string";
printf("%s", p);
p = "start";
printf("%s", p);
This is allowed. Here we are changing the address stored in the pointer variable p to address of the string start(again start is also a read only data in text segement). If you want to modify values present in *p means go for dynamically allocated memory.
char *p = NULL;
p = malloc(sizeof(char)*7);
strcpy(p, "string");
Now p[0] = 'x' operation is allowed, because now we are writing in heap.

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

Resources