I am trying to access all elements of this preinitialized char pointer in 'c'. Here is the code:
#include <stdio.h>
#include <stdlib.h>
void main()
{
char **s="Hello";
printf("%c",*(*&s+1));
}
This code should output "e", but doesn't. What am I doing wrong?
Also, how do I access all elements one by one?
The type of s is incorrect. The string constant "Hello" has array type which can decay to type char * but you're assigning it to a variable of type char **.
Change the type of s to char * and your code will output "e":
char *s = "Hello";
Also, looking at this:
*(*&s+1)
When * comes right before & they cancel each other out. So you can simplify this to:
*(s+1)
Or equivalently:
s[1]
Assumed that you are not seeing the 'e' of the Hello, I highly recommend watching this post.
What to do when the pointer doesn't print the string properly
Just to summarize, when you reference the pointer s, it is only reading the H of Hello (since that is how the pointer of string works - it points to the first character of the string, like s[0]), and that results your code in printing out H only.
Most importantly, your pointer is double-pointer, which is incorrect.
Try it in this way.
#include <stdio.h>
#include <stdlib.h>
void main()
{
char s[] = "Hello";
printf("%s\n",s);
}
Related
I created a string in the main body and I want a function to access it. In order to access it I have to use the name of the string, not the pointer to it:
#include <stdio.h>
void test(char * s,char * b){
printf("%s\n",s);
//printf("%s\n",*s); this crashes it
printf("%c\n",*b);
}
int main(){
char s[]="string";
char b='b';
char * pointerb=&b;
char * pointerstring=&s;
test(pointerstring,pointerb);
}
Why is line 5 correct and not line 6?
printf("%s\n",*s);
%s is a format specifier for string. it expects pointer to array of char, but you are passing argument type is char. this is the reason for segmentation fault.
another side note, your has warning for this line
char * pointerstring=&s;
need to change to below.
char * pointerstring=s;
char* pointerstring now points to first char of string s[] which is nothing but 's'
Here is stack visualization of how pointer point to the string when program reaches at line char * pointerstring=s;
I'm playing with pointers and array and I found it hard to understand why this code doesn't work.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void change(char **test)
{
char *test1 = malloc(sizeof(char)*17);
strcpy(test1, "HEAP");
*test = test1;
}
int main()
{
char str[15]= "hello World"; //Array of char
change(&str); // Passing the address of my array of char
printf("%s", str);
}
The goal is to change the address of strto the allocated memory array inside the function change
But changing the line :
char str[15]= "hello World";
to this (which is read only right ?):
char *str= "hello World";
Also, I'm getting a warning when compiling that I don't understand either :
main.c:17:12: warning: passing argument 1 of ‘change’ from incompatible pointer type [-Wincompatible-pointer-types]
17 | change(&str); // Passing the address of my array of char
| ^~~~
| |
| char (*)[15]
main.c:5:20: note: expected ‘char **’ but argument is of type ‘char (*)[15]’
5 | void change(char **test)
Thank you !
char str[15] isn't a pointer so you can't change its address. You need str to be a char*.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HEAP "HEAP"
void change(char **test)
{
char *test1 = malloc(sizeof HEAP); // sizeof(char) is defined to be 1
strcpy(test1, HEAP);
*test = test1;
}
int main()
{
char orig[] = "hello World";
char *str = orig; // initialize it to point at the first char in orig
printf("before: %s\n", str);
change(&str);
printf("after : %s\n", str);
free(str); // free what you've allocated
}
The goal is to change the address of strto the allocated memory array inside the function change...
You cannot change the address of a variable. If a variable is a non-const pointer, you can make it point to some other memory address, provided it should be of compatible type with the type of pointer.
Before moving ahead, a couple of points for array:
Arrays are not pointers. They both are different.
In C, array names are non modifiable lvalues.
The warning message that you are getting is very clearly conveying the message - the type of argument that you are passing to change() function is not compatible with type of its parameter. The type of &str argument (passing to change()) is char (*)[15] and type of test parameter is char **.
Lets change the type of test parameter of change() function and make it compatible with the type of &str that you are passing to change() function and check what happens!
Make the following change in your program
void change(char (*test)[15])
^^^^^^^^^^^
With this change when you compile your program, you will get following error:
# gcc -Wall -Wextra prg.c
prg.c:10:11: error: array type 'char [15]' is not assignable
*test = test1;
~~~~~ ^
1 error generated.
The error is occurring because test is a pointer pointing to str array and when you dereference it (i.e. *test) you get the array of type char [15] and, that means, this statement will end up attempting to assign test1 to array of type char [15] (which, in this context, is array str). Check the second point above - array names are non modifiable lvalues. Hence, this error is occurring.
So, arrays are non assignable, however, you can change the content of array in change() function using the address of str that you passing to change() function. You can do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_CHARS 15
void change(char (*test)[NUM_CHARS]) {
strcpy (*test, "HEAP");
}
int main (void) {
char str[NUM_CHARS]= "hello World"; //Array of char
printf ("Before calling change(), str : %s\n", str);
change (&str); // Passing the address of my array of char
printf ("After calling change(), str : %s\n", str);
return 0;
}
Output:
# ./a.out
Before calling change(), str : hello World
After calling change(), str : HEAP
Note, that same you can achieve with passing the str to change() function, instead of passing address of str (Of course, you have to make respective changes in the change() function as well).
How to make a pointer pointing so some other memory inside a function is already shown in other post (by #Ted Lyngmo).
Follow good programming practice:
Always check the malloc() return.
Make sure to free the dynamically allocate memory once done with it.
Purpose : My main purpose was to create a string in some kind of function , it should return an adress , by returning adress using the string in main.
But I learned char array and char pointer actually using for the same purpose.
If we suppose that's true , We have these declaration :
char *arr and char arr[10] , *(arr+9)=arr[10] isn't it?
Application 1 does not work.
Application 2 does work fine.
Application 1:
#include <stdio.h>
char *foo(char arr[]);
int main(void)
{
char example[10];
example=foo(example);
printf("%s\n",example);
return 0;
}
char *foo(char arr[])
{
arr[10]="attempt";
return arr;
}
Application 2:
#include <stdio.h>
char *foo(char*);
int main(void)
{
char *example;
example=foo(example);
printf("%s\n",example);
return 0;
}
char *foo(char* arr)
{
arr="attempt";
return arr;
}
Your code will invoke undefined behavior in both segments. ( Even though you have observed that Code 2 works, it only seems to work. In reality a failure is lurking, and can show without warning. )
Make these corrections to address that problem, and see comments for explanations:
In code 1:
//int main(void){
int main(void){//int main(void) is minimum prototype for main function.
//char example[10]; // this will invoke undefined behavior
char example[10] = {"something"}; // 'example' initialized with content,
// thus averting undefined behavior
//example=foo(example);
strcpy (example, foo(example)); // char array is not assignable using `=`
// use strcpy to transfer result of "foo"
printf("%s\n",example);
return 0;
}
char *foo(char arr[]) //note: char arr[] decays into char *arr
{
//char arr[10]="attempt"; // Error: redefinition of 'arr' with a
// different type: char[10] vs char *
arr = "attempt"; //because char [] decays into char *, 'arr' is usable as is.
return arr;
}
To answer your question in comments: Why using strcpy function [after variable example was initialized] is not a undefined behaviour.
First the definition of a C string is important to know. ( C string definition is found here. )
The variable example in its original form, i.e. initialized:
char example[10];
Can contain anything. For example:
|%|h|8|\#|d|o|-|~|*|U|?|?|?|?|
// ^end of memory for 'example`
// note that the character in example[9] == 'U', not NULL, therefore, not a C string.
This would cause the function strcpy() to fail. Initializing guarantees predictable results:
char example[10] = {"something"};//properly initialized
|s|o|m|e|t|h|i|n|g|0|?|?|?|?|
// ^end of memory for 'example`
//or
char example[10] = {0}; //also properly initialized
|0|0|0|0|0|0|0|0|0|0|?|?|?|?|
// ^end of memory for 'example`
(This would require an extra step to place proper content.):
strcpy(example, "something");
The only required adjustment to Code 2 is to initialize the pointer before using: (See the reason why pointer must be initialized here.)
char *foo(char*);
//int main(void){
int main(void){//int main(void) is minimum prototype for main function.
{
//char *example; // passing this will envoke undefined behavior
char *example = NULL;// must initialize before using
example=foo(example);
printf("%s\n",example);
return 0;
}
char *foo(char* arr)
{
arr="attempt";
return arr;
}
Both do not "work" for different reasons.
The first is undefined behavior (UB) as code attempts to assign an element outside the bounds of example[10].
arr[0]='\0'; or arr[9]='\0'; would have been OK given the value passed to foo().
Converting the address of the string literal "attempt" to a char is not good code either. A well enabled compiler will warn of this basic coding lapse. #f3rmat example
char *foo(char arr[]) {
arr[10]="attempt"; <-- UB
return arr;
}
char example[10];
example=foo(example);
The 2nd is UB because code attempted to use an uninitialized value in passing a pointer. This "works" in that the UB of passing an uninitialized pointer is often benign. Since foo() does not use this "garbage" value and the rest of good is well defined, it "works".
char *foo(char* arr) {
arr="attempt";
return arr;
}
char *example;
example=foo(example); // UB - likely a garbage value is passed to `foo()`.
printf("%s\n",example); // `example` is now pointing to `"attempt"`.
I learned char array and char pointer actually using the same purpose.
Pointers and arrays are related, yet different. Avoid the "actually using the same purpose" idea.
An array is like a row of houses on a street. A pointer is the address of a house written on a piece of paper in your hand. Houses ≠ scrap of paper. You can refer to the house by its address or even a row of houses by the first house's address, yet a house and its address are different.
I tried to compile Code '1' and got the following error:
prog.c: In function ‘main’:
prog.c:8:12: error: assignment to expression with array type
example=foo(example);
prog.c: In function ‘foo’:
prog.c:14:12: warning: assignment makes integer from pointer without a cast [-
Wint-conversion]
arr[10]="attempt\n";
^
You get error: assignment to expression with array type example=foo(example); because in your left hand side, you're using an array type, which is not assignable. Assignment operator (=) needs to have a modifiable lvalue as its left operand.
You get a warning: assignment makes integer from pointer without a cast [Wint-conversion] arr[10]="attempt\n"; because the left hand side and the right hand side in this assignment have different types.
Pointer and array are not the same.
char *arr = "attempt"
Here you're creating a string constant "attempt" and assigning its address to arr which is valid
char arr[10];
arr = "attempt";
This is invalid.
you can add elements to the array by following methods.
char arr[10] = "attempt";
char arr[10] = {'a', 't', 't', 'e', 'm', 'p', 't'};
arr[0] = 'a';
arr[1] = 't'; // and so on.
when you are passing the array as an argument to another function
arr = foo(arr);
you are passing the address of the zeroth element in the array arr[0]
Hope that helps..
Char arrays can be initialized but cannot be assigned.
char example[10]="attempt";
is valid.
But
char example[10];
example="attempt"
is not valid.
More details here
Your second example works because you pass a uninitialized pointer to a function and return an address of the string literal attempt
which will work perfectly as mentioned in the answer by chux
I was just going through certain interview questions. Got this structure related issue, I m not understanding what is happening wit the output, Please if some could explain the reason.
When is use a character pointer in the structure like
#include <stdio.h>
struct name {
char *array;
}variable;
int main( int argc, char * argv[] ){
variable.array="hello";
printf( "%s\n", variable.array );
}
The output is hello printed, but when change the structure variable to
struct name {
char array[10];
}variable;
The compiler throws an error "incompatible types in assignment" at
variable.array="hello";
I am really confused as to where i am missing the point. Why does it show the error like assignment problem?? Please correct me
Thank you
You can only initialize array like that at the time of declaration only,
else you need to use
strcpy(variable.array,"hello");
you can't even do like that with a simple char array
char a[10];
a="hello";
the complier will tell :
incompatible types when assigning to type ‘char[10]’ from type ‘char *’
because "hello" is a string literal that is being held by a pointer which can't be assigned like this to an array.
In C the term "hello" means "a pointer to a string that has the chars 'hello\0' in it".
So when you assign array="hello" in the first case you are assigning the pointer to the string into a pointer variable. Which is right.
In the second case you try to assign a pointer to an array which is wrong!
you can't assign value to an array.
It raises an error because an array of char and a pointer to char are different things.
An array is not a pointer. A pointer is not an array. Sometimes a pointer might point to an array. But even when a pointer points to an array, it's not an array.
Your compiler gives an address to variable.array at compile time. It also gives an address to the string literal "hello". They're not the same address. The string literal and the array (or "the buffer") are in different places; logically, the string has to be copied into the buffer.
#include <stdio.h>
#include <string.h>
struct name {
char array[10];
}variable;
int main( void ){
strcpy(variable.array, "hello");
printf( "%s\n", variable.array );
return 0;
}
You might find the C FAQ useful.
The first thing is array is a constant pointer to the first element in the
array,we can not change its address location once we declared..like
int a[3]; is equivalent to int *const a;
so we cant change the array address location
int a[3]={1,2,3};
a++;//its an error
int b[3];
b=a;//its also an error
but int *c;
c=a;//Not an error because c is a pointer to integer not constant pointer to integer
similar to
char str[10]="hello";
if i change like this
str="world";//its also an error
Pointers and arrays are always not equal, in some cases only like dereferencing
char a[10]="hello";
for(i=0;a[i]!='\0';i++)
printf("%c",a[i]);
for(i=0;a[i]!='\0';i++)
printf("%c",*(a+i));
I am learning C programming and I have a simple question about pointers...
I used the following code to play around with pointers:
#include <stdio.h>
int main (int argc, const char * argv[]) {
int * c;
printf("%x\n",c);
return 0;
}
When I print the value of C, I get back a 0. However, when I print &c (i.e. printf("&x\n",&c) I get an address in memory...
Shouldn't I be getting an address in memory when printing the pointer (i.e. printf("%x\n",c)?
--- EDIT ---
#include <stdio.h>
#include <stdlib.h>
int main (int argc, const char * argv[]) {
char * a = malloc(11);
printf("String please\n");
scanf("%s",a);
printf("%s",a);
}
The question is, why does printf("%s",a) returns the string instead of the address that is stored in a?
Shouldn't I use *a to follow the pointer and then print the string?
your current program is not correct. You define variable and do not set value before first use. the initial value is not guranteed for c, but you are lucky and it is equal to 0. It means that c points to nowhere. when you print &c you print address of variable c itself. So actually both versions print address.
printf is actually quite a complex function and can be made to do all sorts of tricks by giving it the right format specifier.
In your string example:
printf("%s", a)
the "%s" tells the printf function that the following variable should be treated as a string. In C, a string is a pointer to one or more char, terminated by a char containing 0. This is a pretty common request, which is why printf supports a format specifier "%s" that triggers this relatively complex behavior. If you want to print the address contained in the string pointer you have to use the format you found earlier:
printf("%x\n",a);
which tells printf to treat the contents of a as an unsigned integer, and print it in base 16.
*a would just be the value pointed to by a, which is just a single character.
You could print the single character with
printf("%c", *a);
Having int* c; If you print value of c, you get back a value that should be interpreted as a memory address of an integer value. In you example it might be 0 or something completely different as you are not initializing c.
If you print &c you get memory address of the pointer c (stored in stack).
#include <stdio.h>
int main (int argc, const char * argv[]) {
int * c;
int a=10;
c = &a;
printf("%x\n",c);
return 0;
}
This may clarify what happens when you make the int pointer point to something in memory.