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));
Related
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
My question is about dereferencing a char pointer
Here is my code -
#define MAX 10
char s[80]="Hello";
int main(){
char *stackValue;
stackValue=&s;//here I assined the address of s to stackValue
if(!stackValue){
printf("No place for Value");
exit(1);
}
else{
printf("\n%s",*stackValue);//This doesn't work with * before it
printf("\n%s",stackValue);//This works properly
}
return 0;
}
In the above code I have assigned the address of S[] to stackValue and when I am printing *stackValue it doesn't work ,
But If I print only 'stackValue' That works.
When I do same thing with Integer
int main(){
int i=10, *a;
a=&i;
printf("%d",*a);//this gives the value
printf("%d",a)//this gives the address
return 0;
}
Is printing char pointer and integer pointer is different. When I use * in int value it gives the value but gives an error when I use it as a char pointer.
Help me out?
With the first code snippet:
stackValue=&s; is incorrect given s is already an array to char. If you write like that then stackValue becomes pointer to pointer to char (not pointer to char).
Fix that by changing to stackValue=s;
Also, again %s expect a pointer to char (NOT pointer to pointer to char) - that explains why this doesn't work
printf("\n%s",*stackValue); // this doesn't work
You need printf("\n%s",stackValue); instead.
With the second code snippet.
a=&i; is ok because i is a single int, NOT an array.
What you are trying to do is this:
int main(void)
{
char a_data = "Hello, this is example";
char *pa_stack[] = {a_data};
printf("We have: %s\n", *pa_stack);
}
The "%s" format specifier for printf always expects a char* argument.
so this is working and correct statement
printf("\n%s",stackValue);
and in first statement you are passing value so it will give you undefined behaviour.
I have program
void alloc(char **p)
{
*p=(char*)malloc(sizeof(char)*3);
(*p)[0]='a';
(*p)[1]='f';
(*p)[2]='\0';
}
main()
{
char p[]="hrrgr";
alloc(&p);
printf("%s",p);
}
It prints nothing. Please explain this.
I know by passing char*p ; and alloc(&p) will do the trick. But the purpose of my question is to understand the output I am getting.
p is an array of 6 characters. Therefore p is of type char[6]. &p is then of type pointer to char[6] type, i.e., char (*)[6]. When you pass an array to a function, it evaluates to a pointer to its first element. Thus when you are passing a char (*)[6] type value to your alloc function, you are assigning a char (*)[6] type to a char ** type. They are incompatible types and have different pointer arithmetic. You can't make char (*)[6] behave like a char ** type, even by typecasting which will only suppress compiler warning.
This is not allowed: p is an array of 6 characters, not a char pointer. You should not treat &p as a char** pointer.
If you want to fix this code, declare p like char*, not as an array:
char *p="hrrgr";
alloc(&p);
Running demo on ideone.
&p is of type char (*)[6] but your function alloc expects an argument of type char **. You are passing wrong type parameter.
try this...
void alloc(char **p)
{
*p=(char*)malloc(sizeof(char)*3);
(*p)[0]='a';
(*p)[1]='f';
(*p)[2]='\0';
}
main()
{
char *p;
alloc(&p);
printf("%s",p);
}
When ever you declare an array then there will be continuous allocation of memory but here your are changing starting 3 elements memory which changes the whole location of array and printing garbage...
Can somebody tell me why this program does not work?
int main()
{
char *num = 'h';
printf("%c", num);
return 0;
}
The error I get is:
1>c:\users\\documents\visual studio 2010\projects\sssdsdsds\sssdsdsds\sssdsdsds.cpp(4): error C2440: 'initializing' : cannot convert from 'char' to 'char *'
But if I write the code like that:
int main()
{
char num = 'h';
printf("%c", num);
return 0;
}
it's working.
char *num = 'h';
Here, the letter 'h' is a char, which you are trying to assign to a char*. The two types are not the same, so you get the problem that you see above.
This would work:
char *num = "h";
The difference is that here you're using double-quotes ("), which creates a char*.
This would also work:
char letter = 'h';
char* ptrToLetter = &letter;
You should read up on pointers in C to understand exactly what these different constructions do.
char * is a pointer to a char, not the same thing than a single char.
If you have char *, then you must initialize it with ", not with '.
And also, for the formatting representation in printf():
the %s is used for char *
the %c is only for char.
In thefirst case you declared num as a pointer to a char. In the second case, you declare it as a char. In each case, you assign a char to the variable. You can't assign a char to a pointer to a char, hence the error.
'h' = Char
"h" = Null terminated String
int main()
{
char *num = "h";
printf("%s", num); // <= here change c to s if you want to print out string
return 0;
}
this will work
As somebody just said, when you write
char *num = 'h'
The compiler gives you an error because you're trying to give to a pointer a value. Pointers, you know, are just variables that store only the memory address of another variable you defined before. However, you can access to a variable's memory address with the operator:
&
And a variable's pointer should be coerent in type with the element pointed.
For example, here is how should you define correctly a ptr:
int value = 5;
//defining a Ptr to value
int *ptr_value = &value;
//by now, ptr_value stores value's address
Anyway, you should study somewhere how this all works and how can ptrs be implemented, if you have other problems try a more specific question :)
When you are using char *h, you are declaring a pointer to a char variable. This pointer keeps the address of the variable it points to.
In simple words, as you simply declare a char variable as char num='h', then the variable num will hold the value h and so if you print it using printf("%c",num), you will get the output as h.
But, if you declare a variable as a pointer, as char *num, then it cannot actually hold any character value. I can hold only the address of some character variable.
For example look at the code below
void main()
{
char a='h';
char *b;
b=&a;
printf("%c",a);
printf("%c",b);
printf("%u",b);
}
here , we have one char variable a and one char pointer b. Now the variable a may be located somewhere in memory that we do not know. a holds the value h and &a means address of a in memory The statement b=&a will assign the memory address of a to b. Since b is declared as a pointer, It can hold the address.
The statenment printf("%c",b) will print out garbage values.
The statement printf("%u",b) will print the address of variable a in memory.
so there's difference between char num and char *num. You must first read about pointers. They are different from normal variables and must be used very carefully.
#define STRMAX 50
struct Person {
char sName[STRMAX];
int iAge;
};
typedef struct Person PERSON;
int main() {
PERSON *personen[1];
personen[0]->sName = "Pieter";
personen[0]->iAge = 18;
return 0;
}
This code generates an error on personen[0]->sName = "Pieter"; saying incompatible types in assignment. Why?
You don't want an array of pointers. Try
PERSON personen[1];
And like others have said, use the strcpy function!
Don't try to assign arrays. Use strcpy to copy the string from one array to the other.
...sName is an array of chars while "Pieter" is a const char*. You cannot assign the latter to the former. The compiler is always right :)
Change
PERSON *personen[1];
to
PERSON personen[1];
and use strcpy to copy the string.
strcpy(personen[0]->sName,"Pieter");
I agree with the above but I figured it was also important to include the "why"
int a; // is an integer
int *b; // pointer to an integer must be malloced (to have an array)
int c[]; // pointer to an integer must also be malloced (to have an array)
int d[5]; // pointer to an integer bu now it is initialized to an array of integers
to get b and c from simple pointers and give them memory to match d use the following to give them memory space
b = (int *) malloc(sizeof(int)*5);
where it casts the pointer returned from malloc to an int pointer, and creates a memory block of 5 times the size of an integer (thus it will hold 5 integers like d)