I have this simple structure I want to initialize on the heap and return as a pointer in a function.
struct entry {
const char* const key; // We don't want the key modified in any way
const void* data; // But the pointer to data can change
struct entry* next;
};
There is one problem, I cannot calloc it and initialize members one by one because key is a const pointer. I found somewhere this syntax that works:
struct entry* entry = calloc(1, sizeof(struct entry));
*entry = (struct entry) { .key = key, .data = data, .next = NULL };
But I don't know what is going on with it: does it create an "anonymous" struct that is then copied to the place where *entry lives? Is that safe to use or should I prefer creating a local struct that is then copied with memcpy to the right location?
The assignment you presented is not correct and should not compile.
The correct way of initializing an allocated struct with const members is to allocate some memory, create a temporary struct entry object, and then use memcpy to copy the object to the allocated memory:
void* mem = malloc( sizeof( struct entry ) );
struct entry temp = { key , data , NULL };
memcpy( mem , &temp , sizeof( temp ) );
struct entry* e = mem;
This line:
*entry = (struct entry) { .key = key, .data = data, .next = NULL };
uses the assignment operator. The conditions for assignment operator (C11 6.5.16/2) include:
Constraints
An assignment operator shall have a modifiable lvalue as its left operand.
The definition of modifiable lvalue can be found in 6.3.2.1/1:
A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.
So *entry is not a modifiable lvalue, because its type is a struct that has a member with const-qualified type. Therefore it is a constraint violation to have *entry appear on the left-hand-side of the assignment operator.
The clang compiler (all versions I tried) appears to not give any diagnostic message for this constraint violation; this is clearly a compiler bug. gcc does give a diagnostic.
Regarding the second part of the question:
should I prefer creating a local struct that is then copied with memcpy to the right location?
As also explained by 2501, you can do this in C when writing into space allocated by the malloc family. (If you had declared a named struct entry object then it is less clear whether memcpying over it is permitted).
Related
struct payload{
struct metadata meta;
char data_pointer[0];
};
struct payload* mypayload = (struct payload*) malloc(sizeof(struct payload) + 50);
What is the type of mypayload here?
The address, pointer, or something else
malloc returns an untyped chunk of memory, and the assignment is how you tell the compiler what type it is. In this case struct payload * which is a pointer (an address) of the memory that was allocated or NULL if the allocation failed.
You don't need the cast (struct payload*).
If you want data_pointer to be a flexible array member, then you leave the size unspecified char data_pointer[];. An array of size 0 is undefined behavior.
What is the type of mypayload here?
mypayload is a pointer, a pointer to a struct payload. #kaylum
A struct array member with size 0, like char data_pointer[0]; is not defined by C although some implementations had allowed it as a pre-cursor to a flexible array member (FAM).
Since C99 use char data_pointer[]; to define the last member as a flexible array member.
To best allocate for a flexible array member, compute the sum of 2 sizes:
sizeof mypayload[0]: Size of the object up to, but not including the FAM member. This will include any padding before the FAM member.
sizeof mypayload->data_pointer[0]: Size of the FAM referenced data times the count, 50, of array elements desired.
Tip: a type is not needed in the sizeof code. Easier to code right, review and maintain to use the size of the referenced object.
Tip: Cast not needed.
Tip: Check for allocation success.
Example:
struct payload{
struct metadata meta;
char data_pointer[]; // No 0
};
struct payload* mypayload = malloc(
sizeof mypayload[0] +
sizeof mypayload->data_pointer[0] * 50);
if (mypayload == NULL) {
; // TBD code to handle out-of-memory
}
mypayload is a pointer. It's a pointer to the memory allocated by malloc(). And you have it configured as a pointer to a payload.
I have only been learning C for less than a week (with my knowledge of C++ and other languages to help) and I am confused on pointers and their ways of being declared.
Below, I use a simple struct named Object:
struct Object { int id; };
Do the below methods for creating a pointer do the same thing just in a different way, or no?
struct Object obj1 = { .id = 1 };
struct Object* obj1_p = &obj1; // method 1 of getting a pointer
// The same, just in a compound literal?
struct Object* obj2_p = &(struct Object){ .id = 1 }; // method 2 of getting a pointer
// Is this the same, other than being uninitialized?
struct Object* obj3_p = malloc(sizeof(struct Object)); // method 2 of getting a pointer
Is there a time when you only can use one method?
Also, as a side note, why do some people cast malloc, and is it better to do it?
// malloc is casted to object:
struct Object* obj3_p = (Object*)malloc(sizeof(struct Object));
These two “methods” do exactly the same thing. And as you said, the second one is just a compound literal.
struct Object obj1 = { .id = 1 };
struct Object *obj1_p = &obj1;
// The same, just in a compound literal?
struct Object *obj2_p = &(struct Object){ .id = 1 };
This allocates enough memory for struct Object without initializing it. And no you don't need to cast it, because malloc returns void *, which is automatically and safely promoted to any other pointer. But if you do, you should cast it to struct Object* instead of Object*.
struct Object *obj3_p = (struct Object*) malloc(sizeof(struct Object));
That looks very bulky though... My preferred way of doing it is this:
struct Object *obj3_p = malloc(sizeof *obj3_p);
I wrote this piece of code, hope it helps you to better understand some features of pointers:
#include <stdio.h>
#include <stdlib.h>
struct Object { int id; };
struct Object *getObjectBold() {
struct Object* obj2_p = &(struct Object) { .id = 2 };
return obj2_p; // UB: Returns the address of a local object (the compound literal).
}
struct Object *getObject() {
struct Object* obj3_p = malloc(sizeof(*obj3_p)); // Better way of calling malloc than using sizeof(struct Object).
obj3_p->id = 3; // You don't need to do this.
return obj3_p; // This needs to be freed later on!
}
int main(void) {
struct Object obj1 = { .id = 1 };
struct Object* obj1_p = &obj1;
printf("obj1.id = %d\n", obj1_p->id);
obj1_p->id = 10; // You can change values using the pointer
printf("obj1.id = %d\n", obj1_p->id);
// The only different thing with this case is that you don't
// "lose" your object when setting the pointer to NULL
// (although you can only access it through the object, not through the pointer).
obj1_p = NULL;
printf("obj1.id = %d\n", obj1_p->id); // This won't work (undefined behaviour).
printf("obj1.id = %d\n", obj1.id); // This will.
struct Object* obj2_p = &(struct Object) { .id = 1 };
obj2_p->id = 2; // You can change the id
printf("obj2.id = %d\n", obj2_p->id);
// If you make this pointer point to another address, you "lose" your object.
obj2_p = NULL;
printf("obj2.id = %d", obj2_p->id); // This won't work at all (undefined behaviour).
// Both of these pointers point to objects in the stack, so, for example,
// they don't work when returning from a function.
obj2_p = getObjectBold();
obj2_p->id = 20; // This won't work (undefined behaviour).
printf("obj2.id = %d\n", obj2_p->id); // This works if you don't dereference the pointer.
// The third case is not the same as the other two, since you are allocating memory on the heap.
// THIS is a time where you can only use one of these three methods.
struct Object *obj3_p = getObject(); // This works!
printf("obj3.id = %d\n", obj3_p->id);
obj3_p->id = 30; // This works now.
printf("obj3.id = %d\n", obj3_p->id);
free(obj3_p); // You need to do this if you don't want memory leaks.
return 0;
}
This is the output when commenting out undefined behaviour:
obj1.id = 1
obj1.id = 10
obj1.id = 10
obj2.id = 2
obj2.id = 2
obj3.id = 3
obj3.id = 30
I'd recommend you to check out these links, they turned out to be pretty helpful for me:
Returning a pointer from a function
What and where are the stack and heap?
What EXACTLY is meant by “de-referencing a NULL pointer”?
Why dereferencing a null pointer is undefined behaviour?
Do I cast the result of malloc?
There are two distinct topics in your question.
struct Object* obj1_p = .......;
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^
pointer object initialization
definition
Pointer variable definition
You can define the pointer variable only one way:
type *objectname;
Initialization assigns the value to the pointer variable. This value should reference the valid object of the same type as the pointer or valid memory of the size not smaller than the pointer type. The difference in your examples is how the referenced object is created.
Is there a time when you only can use one method?
That only depends on the program logic. You only must remember about the scope of the underlying object to avoid dereferencing objects which does not exist outside the particular scope:
struct Object *valid1(void) //valid
{
struct Object* obj3_p = malloc(sizeof(*obj3_p));
return obj3_p;
}
struct Object obj1 = { .id = 1 };
struct Object *valid2(void) // valid
{
struct Object* obj3_p = &obj1;
return obj3_p;
}
struct Object *invalid1(void) // invalid
{
struct Object obj1 = { .id = 1 };
struct Object* obj3_p = &obj1;
return obj3_p;
}
struct Object *invalid2(void) // invalid
{
struct Object* obj3_p = &(struct Object){ .id = 1 };
return obj3_p;
}
Also, as a side note, why do some people cast malloc, and is it better
to do it?
It is considered as bad practice as it silences the warning if there is no prototype of the malloc. Better do not cast. Modern compilers and recent C standard disallow the use of the functions without prototypes
It is better to use sizeof(object) instead of sizeof(type) as if you change the type of the object you need to change oll of the occurrences of the sizeof(type) in your program. It very easy to miss some and get very hard to discover errors.
First, let's straighten out some terminology -
You are declaring all three pointers the exact same way:struct Object* objn_p ...
The only difference is in how you are initializing them.
Declarations in C have two major components - a sequence of declaration specifiers followed by a comma-separated list of optionally initialized declarators. C++ declarations are structured fundamentally the same way, but for this answer I will stick with C terminology (since that's the language we're talking about the one I'm more familiar with).
Declaration specifiers include storage class specifiers (auto, static, register, typedef, etc.), type specifiers (int, char, double, short, etc.), type qualifiers (const, volatile, restrict), and a few others.
Declarators include the name of the thing being declared, along with information about its pointer-ness, array-ness, and/or function-ness.
Initializers for scalar objects are scalars. Initializers for aggregate objects like arrays, structs, and unions are brace-enclosed lists or, in the case of character arrays, a string literal.
In the declaration
struct Object* obj1_p = &obj_1;
the declaration specifier is struct Object, the declarator is * obj1_p, and the initializer is = &obj_1.
I know the C++ convention for declaring pointer objects is T* p, but the syntax is actually T (*p) - the * operator is always bound to the declarator, not the type specifier. If you write T* p, q; then only p is declared as a pointer to T; q is declared as an instance of T. I know why the C++ convention exists, I know the justifications for it, but it does misrepresent how declaration syntax works in both C and C++ and I consider it a mistake to use. Most C programmers will use the T *p convention instead1.
Here are the basic rules for pointer declarations in C:
Declaration Declarator
Specifier
----------- ----------
T *p; // p is a pointer to T
T *a[N]; // a is an array of pointer to T
T *f(); // f is a function returning a pointer to T
T (*a)[N]; // a is a pointer to an array of T
T (*f)(); // f is a pointer to a function returning T
The rules for const are:
T const *p; // p points to a const T
const T *p; // same as above
T * const p; // p is a const pointer to T
What differs between your three methods is how you initialize the pointer.
Method 1 is just taking the address of a previously-declared variable of the same type:
struct Object *obj1_p = &obj1; // using the C convention for pointer declarations
Method 2 is taking the address of a compound literal - basically, an anonymous variable:
struct Object *obj2_p = &(struct Object){ .id = 1 };
The only difference between obj1 and the anonymous object is that you can refer to obj1 directly as well as through the pointer:
printf( "%d %d %d", obj1.id, obj1_p->id, (*obj1_p).id );
whereas you can only refer to the anonymous object through the pointer variable
printf( "%d %d", obj2_p->id, (*obj2_p).id );
Method 3 dynamically allocates memory and assigns the address of the resulting object (which may be NULL if the malloc call fails).
struct Object *obj3_p = malloc( sizeof( struct Object ) );
The chief difference between this and the other two methods is that the memory allocated by malloc hangs around until you explicitly free it, whether the obj3_p variable goes out of scope or not. If obj1 and the anonymous object are declared within a block and without the static keyword, then that memory is automatically released when the block containing them exits.
Also, as a side note, why do some people cast malloc, and is it better to do it?
There are two times when you must cast the result of malloc (and calloc and realloc):
You are compiling the code as C++;
You are working with an ancient, pre-C89 K&R implementation.
Unlike C, C++ does not allow implicit conversion between void * (the type returned from malloc) and other pointer types. You must explicitly cast conversions to or from void *. Having said that, if you're writing C++ you should not be calling malloc directly. You should either be using a container that manages memory for you under the hood (std::string, std::vector, std::map, etc.) or you should be using the new or new [] operators. If you're in the middle of a lift-and-shift from C to C++, it's acceptable to keep the malloc calls until you can get around to rewriting your memory management code, but ideally C++ code should never use malloc (or calloc or realloc) directly.
In the earliest versions of C, malloc, calloc, and realloc returned char *, so you had to cast the result if you were assigning it to pointers of different types:
int *p = (int *) malloc( sizeof *p * N );
As someone who wrote K&R C in college, this was a pain in the ass. It was cluttered and a constant source of mistakes. If you changed the type of p (say from int * to long *) you had to repeat that change in multiple places. That created a higher maintenance burden, especially if (as was often the case) the pointer declaration was separated from the malloc call by other code:
int *p = NULL;
...
p = (int *) malloc( sizeof *p * N );
Prior to C99, you had to declare all variables before any statements (in that block, anyway), so it was common for pointer declarations to be separated from the malloc call by multiple lines of code. It was really easy to change the type of *p in the declaration but forget to do it in the assignment later, causing subtle (and sometimes not-so-subtle) runtime errors.
The 1989 standard introduced the void type and changed the *alloc functions to return void *. It also introduced the rule that you could assign void * values to other pointer types and vice versa without an explicit cast. So you could write a malloc call as:
int *p = malloc( sizeof *p * N );
or
int *p = NULL;
...
p = malloc( sizeof *p * N );
If you change the type of *p, you only have to make that change in one place. It's cleaner, it's harder to screw up, etc.
Also, under the C89 standard, casting the result of malloc could suppress a useful compiler diagnostic if you forgot to include stdlib.h or otherwise didn't have a declaration for malloc in scope. But since C99 did away with implicit int declarations2, that's not really an issue anymore.
However, there are people who prefer to keep the explicit cast for various reasons. Personally, I have found those reasons wanting, and I've accumulated enough scar tissue from bad casts that I prefer to leave them off entirely. 30+ years of writing code has convinced me that when it comes to memory management, simpler is always better. It doesn't hurt to use them; they don't slow down the code or anything like that. But from a readability and maintenance standpoint, casting malloc is bad juju.
Whitespace in declarations is only significant in that it separates tokens. The * character is a token on its own and not part of any identifier, so you can write any of T *p, T* p, T*p, or T * p and they will all be parsed as T (*p).
Prior to C99, if the compiler saw a function call without a preceding declaration, it assumed the function returned int, so if you forgot to include stdlib.h the compiler would complain if you tried to assign the result of malloc to a pointer since an int can't be implicitly converted to a pointer. However, if you used the cast, then the diagnostic would be suppressed.
How to assign an array wrapped into a struct using the struct pointer?
I know this syntax:
size_t initArrayList[] = {1,1,1};
memcpy(pStruct->sizet, initArrayList, sizeof(pStruct->sizet));
is it possible to use a similar syntax as:
Stru = (struct myStruct) {.sizet = {1,1,1}};
using pointers?
I'd appreciate a detailed explanation of what (struct myStruct) {.sizet = {1,1,1}} does.
struct myStruct {
size_t sizet[3];
} ;
void struInit(struct myStruct * pStruct) ;
int main()
{
struct myStruct Stru;
struInit(&Stru);
if (Stru.sizet[1]==1)
printf("\nStru.sizet[1]==1");
return 0;
}
void struInit(struct myStruct * pStruct ) {
// I know this syntax
// size_t initArrayList[] = {1,1,1};
// memcpy(pStruct->sizet, initArrayList, sizeof(pStruct->sizet));
}
Either calling memcpy using a temporary array (just as commented out in your struInit function)
memcpy(pStruct->sizet, initArrayList, sizeof(pStruct->sizet));
or assigning to the pointed-to structure using a compound literal (notice the use of the * dereference operator)
*pStruct = (struct myStruct){.sizet={1,1,1}};
or even a conventional for-loop, copying element by element, does what you want.
Or if you can not rely on designated initializers or compound literals,
both being features that have only been standardized since C99, you can
use an equivalent, C89 way, that doesn't make use of them:
struct myStruct tmp = {{1,1,1}};
*pStruct = tmp;
I'd appreciate a detailed explanation of what (struct myStruct) {.sizet = {1,1,1}} does.
The relevant parts of C99 describing designated initializers and
compound literals are 6.7.8 Initialization and 6.5.2.5 Compound
literals.
The short answer is that if used in the struInit function it
constructs a local unnamed object with the type struct myStruct,
initializing its member sizet to {1,1,1}, this in turn being syntax
for array element initialization, assigning a value of 1 to its
elements [0], [1], and [2], in that exact order.
I have the following struct and tried to use malloc to create a new object dynamically. It seems to work now with object_ptr obj_ptr1 = malloc(sizeof(object_ptr)); This only assigns the pointer size of object_ptr to obj_ptr1 ? but how do you assign the size of the original struct _object_t in this case?
typedef struct
{
int struct_id;
void *(*function)(void *);
int status;
} _object_t;
typedef struct _object_t* object_ptr;
/* create a new object */
object_ptr obj_ptr1 = malloc(sizeof(object_ptr));
Typedefs for pointer types are often a bad idea, since they can make it difficult to tell whether a type name refers to a pointer type or not.
Suggestion:
typedef struct { /* ... */ } object_t;
object_t *obj1 = malloc(sizeof *obj1);
And if you want to allocate space for an array of N objects:
object_t *obj1 = malloc(N * sizeof *obj1);
Note that I've removed the leading underscore from the type name. Identifiers starting with underscores are reserved to the implementation; you shouldn't define them in your own code.
The malloc(sizeof *foo) idiom may take a little getting used to, but it means you don't have to specify the type name more than once, which avoids errors. (The *obj1 doesn't actually dereference obj1, since the operand of sizeof is not evaluated.)
In your code:
object_t obj1 = malloc(sizeof(object_t));
since object_t is a pointer type, you're allocating enough memory to hold a pointer object, not a structure object. (Using such similar names object_t and _object_t for the pointer and struct types, respectively, undoubtedly contributed to the confusion.)
The problem is in your malloc line. You must allocate sizeof(_object_t) not sizeof(object_t)
Hey I am getting this error:
error: conversion to non-scalar type requested
Here are my structs:
typedef struct value_t value;
struct value{
void* x;
int y;
value* next;
value* prev;
};
typedef struct key_t key;
struct key{
int x;
value * values;
key* next;
key* prev;
};
Here is the code that is giving me problems:
struct key new_node = (struct key) calloc(1, sizeof(struct key));
struct key* curr_node = head;
new_node.key = new_key;
struct value head_value = (struct value) calloc(1, sizeof(struct value))
Am I not suppose to use calloc on structs? Also, I have a struct that I have created and then I want to set that to a pointer of that same struct type but getting an error. This is an example of what I am doing:
struct value x;
struct value* y = *x;
this gives me this error
error: invalid type argument of ‘unary *’
When I do y = x, I get this warning:
warning: assignment from incompatible pointer type
You are trying to assign a pointer expression (the return type of malloc() and friends is void*) to a struct type (struct new_node). That is nonsense. Also: the cast is not needed (and possibly dangerous, since it can hide errors)
struct key *new_node = calloc(1, sizeof *new_node);
the same problem with the other malloc() line:
struct value *head_value = calloc(1, sizeof *head_value);
More errors: You are omitting the 'struct' keyword (which is allowed in C++, but nonsense in C):
struct key{
int x;
struct value *values;
struct key *next;
struct key *prev;
};
UPDATE: using structs and pointers to struct.
struct key the_struct;
struct key other_struct;
struct key *the_pointer;
the_pointer = &other_struct; // a pointer should point to something
the_struct.x = 42;
the_pointer->x = the_struct.x;
/* a->b can be seen as shorthand for (*a).b :: */
(*thepointer).x = the_struct.x;
/* and for the pointer members :: */
the_struct.next = the_pointer;
the_pointer->next = malloc (sizeof *the_pointer->next);
I don't think you've correctly understood typedefs.
The common idiom with using typedefs for convenience naming is this:
struct foo {
int something;
};
typedef struct foo foo_t;
Then you use the type foo_t instead of the less convenient struct foo.
For convenience, you can combine the struct declaration and the typedef into one block:
typedef struct {
int something;
} foo_t;
This defines a foo_t just like the above.
The last token on the typedef line is the name you're assigning. I have no idea what the code you wrote is actually doing to your namespace, but I doubt it's what you want.
Now, as for the code itself: calloc returns a pointer, which means both your cast and your storage type should be struct key* (or, if you fix your naming, key_t). The correct line is struct key* new_node = (struct key*)calloc(1, sizeof(struct key));
For your second, independent, issue, the last line should be struct value* y = &x;. You want y to store the address of x, not the thing at address x. The error message indicates this - you are misusing the unary star operator to attempt to dereference a non-pointer variable.
struct key new_node = (struct key) calloc(1, sizeof(struct key));
calloc returns a pointer value (void *), which you are trying to convert and assign to an aggregate (IOW, non-scalar) type (struct key). To fix this, change the type of new_node to struct key * and rewrite your allocation as follows:
struct key *new_node = calloc(1, sizeof *new_node);
Two things to note. First of all, ditch the cast expression. malloc, calloc, and realloc all return void *, which can be assigned to any object pointer type without need for a cast1. In fact, the presence of a cast can potentially mask an error if you forget to include stdlib.h or otherwise don't have a declaration for malloc in scope2.
Secondly, note that I use the expression *new_node as the argument to sizeof, rather than (struct key). sizeof doesn't evaluate it's operator (unless it's a variable array type, which this isn't); it just computes the type of the expression. Since the type of the expression *new_node is struct key, sizeof will return the correct number of bytes to store that object. It can save some maintenance headaches if your code is structured like
T *foo;
... // more than a few lines of code
foo = malloc(sizeof (T))
and you change the type of foo in the declaration, but forget to update the malloc call.
Also, it's not clear what you're trying to accomplish with your typedefs and struct definitions. The code
typedef struct value_t value;
struct value{
void* x;
int y;
value* next;
value* prev;
};
isn't doing what you think it is. You're creating a typedef name value which is a synonym for an as-yet-undefined type struct value_t. This value type is different from the struct value type you create later (typedef names and struct tags live in different namespaces). Rewrite your structs to follow this model:
struct value_t {
void *x;
int y;
struct value_t *next;
struct value_t *prev;
};
typedef struct value_t value;
Also, life will be easier if you write your declarations so that the * is associated with the declarator, not the type specifier3. A declaration like T* p is parsed as though it were written T (*p). This will save you the embarrassment of writing int* a, b; and expecting both a and b to be pointers (b is just a regular int).
1 - This is one area where C and C++ differ; C++ does not allow implicit conversions between void * and other object pointer types, so if you compile this as C++ code, you'll get an error at compile time. Also, before the 1989 standard was adopted, the *alloc functions returned char *, so in those days a cast was required if you were assigning to a different pointer type. This should only be an issue if you're working on a very old system.
2 - Up until the 1999 standard, if the compiler saw a function call without a preceding declaration, it assumed the function returned an int (which is why you still occasionally see examples like
main()
{
...
}
in some tutorials; main is implicitly typed to return int. As of C99, this is no longer allowed). So if you forget to include stdlib.h and call calloc (and you're not compiling as C99), the compiler will assume the function returns an int and generate the machine code accordingly. If you leave the cast off, the compiler will issue a diagnostic to the effect that you're trying to assign an int value to a pointer, which is not allowed. If you leave the cast in, the code will compile but the pointer value may be munged at runtime (conversions of pointers to int and back to pointers again is not guaranteed to be meaningful).
3 - There are some rare instances, limited to C++, where the T* p style can make code a little more clear, but in general you're better off following the T *p style. Yes, that's a personal opinion, but one that's backed up by a non-trivial amount of experience.
calloc(3) returns a pointer to the memory it allocates.
struct key new_node = (struct key) calloc(1, sizeof(struct key));
should be
struct key* new_node = calloc(1, sizeof(struct key));
You should not assign a pointer to a non-pointer variable. Change new_node to be a pointer.
Also, to use the address of variable, you need &, not *, so change it to struct value* y = &x;
Edit: your typedefs are wrong too. reverse them.
For the second problem, you want to use an ampersand & instead of an astrisk "*`. An astrisk dereferences a pointer, an ampersand gives you the pointer from the value.