#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int *array;
int size;
}Array;
Array array_create(int init_size);
int* array_at(Array *,int index);
void array_free(Array *);
int main(int argc, char const *argv[])
{
Array a =array_create(100);
*array_at(&a,0)=10;
printf("%d\n",*array_at(&a,0));
array_free(&a);
return 0;
}
Array array_create(int init_size){
Array a;
a.size = init_size;
a.array=(int*)malloc(sizeof(int)*a.size);
return a;
}
void array_free(Array *a)
{
free(a->array);
a->array=NULL;
a->size=0;
}
int* array_at(Array *a,int index)
{
return &(a->array[index]);
}
Why did this C language code not report an error or warning? Shouldn't function array_at
only return the value of pointer? Why array_at(&a,0)
is the pointer itself,not the value of the pointer? Why is *array_at(&a,0)
even an lvalue that can be assigned?
Because codes like
#include <stdio.h>
int new(int);
int main(){
int a=3;
new(a)=4;
printf("%d\n",new(a));
}
int new(int i){
i+=3;
return i;
}
won't run sucessfully. I think it's because new(a)
is just a value of the int variable i
and it can't be lvalue, so I really don't understand why the above code can run successfully
Why did this C language code not report an error or warning?
Because the code is not erroneous or particularly dubious.
Shouldn't function
array_at
only return the value of pointer?
Functions return values. Sometimes, as in your case, those values have pointer type. But function call expressions are not lvalues, so the return value is all there is -- there is no underlying object storing it. I think that's what you mean by "only return the value of pointer", so yes.
Why array_at(&a,0) is the pointer itself,not the value of the pointer?
You seem to be confused. array_at(&a,0)
evaluates to a pointer value, but that expression is not an lvalue, meaning that it does designate an object with storage or lifetime. And it does not need to be for the apparent purpose.
Why is *array_at(&a,0) even an lvalue that can be assigned?
Because that's what the unary *
operator produces. Its operand does not need to be an lvalue, and often isn't. Its result, on the other hand, is an lvalue.
And there is nothing unreasonable about that. A valid, non-null pointer value identifies an object. An expression in the unary *
operator designates the object to which the operand points, just like a variable's name designates the object it names. Either way, you can read the designated object's value. Either way, if the object is modifiable at all, you can write the designated object's value.