I'm testing an issue that I'm having when casting void pointers to a different type within the same variable. The issue seems to be when trying to use the same variable for the casted pointer. Below I have a section of code that tests this. Would someone be able to tell me why the program fails to compile for that case?
#include <stdlib.h>
typedef struct test {
int a;
}test;
int main() {
void * check;
test * check2;
check = malloc(sizeof(test));
check = ((test *) check);
check2 = (test *)check;
check->a = 2; //this raises an error (dereferencing void pointer) when compiling
check2->a = 2; //this works
((test *)check)->a = 2; //this also works
}
Casting a pointer is just lying to your compiler
void * ptr = malloc(sizeof(test));
((test *)ptr)->a = 5;
In the second line, we are telling the compiler "I know I declared ptr as a (void *), but I'm smarter than you, and trust me, it's actually a (test *)". Nothing has changed, ptr is still just a pointer, an address of a memory location, but the compiler assumes it's pointing to something specific.
check->a = 2; //this raises an error (dereferencing void pointer) when compiling
You must cast your variables every single time you want the compiler to treat it as something different from what you declared it to be.
A more interesting scenario to explain what you can do with casting pointers...
// struct with two ints, a and b
typedew struct testAB {
int a;
int b;
} testAB;
// struct with two ints, named in reverse order
typedef struct testBA {
int b;
int a;
} testBA;
int main(void) {
// construct a testAB struct
void *ptr = malloc(sizeof(testAB));
((testAB *)ptr)->a = 0
((testAB *)ptr)->b = 1
// treat ptr as a testBA struct
if ( ((testBA *)ptr)->a == 1) {
printf("this shouldn't happen, 'a' was set to 0");
}
}
if you run the above code, you will find that the printf statement will be executed. Even though we set 'a' to be 0, and the if statement checks that a == 1.
This is because structs are stupidly simple. In the above example the struct(s) is just two int's packed next to eachother. Much like an array of two ints, like this:
int array[2] = {0, 1};
void *ptr = &array;
Even with this representation, we can lie to the compiler, we can force the compiler to treat this 'array' as one of our structs.
if ( ((testAB *)array)->a == 0 )
printf("a is 0");
This is because, under the hood, the compiler treats named variables in a struct as just offests from where the struct is.
// the following two lines have the same affect
((testAB *)array)->a = 0;
array[0] = 0;
// the following two lines have the same affect
((testAB *)array)->b = 2;
array[1] = 2;
if we tell the compiler that it's a (testAB *), then 'a' means the first int, and 'b' means the second. If we tell the compiler that it's a (testBA *), then 'a' is the second, and 'b' is the first.
In compiled code ALL variable names are lost. The compiler reduces the struct assignment, down to "set the second int of the struct to 2". Or more specifically, if we are dealing with 32-bit ints, set bytes 5, 6, 7 and 8 of the struct to 0000, 0000 0000 0010 (in binary. (or perhaps in reverse order, if we are compiling for a little endian CPU)
Related
#include <stdio.h>
int main(void)
{
typedef struct{
int a;
} cool;
cool x;
(&x)->a = 3;
x.a = 4;
}
I was wondering if the (&x)-> a does the same thing as the x.a. I coded both of them up, and it seemed that both of them changed the value of x.a. I know it must be a pointer on the left side of ->, but the (&x) seems to work without problem. Printing out x.a works for both of them, and gives me the correct answer. I looked up a lot about pointers, linked list, and structures and am still not able to find out the answer. Would it be possible to get an explanation? Thank you!
The -> operator expects a pointer on the left hand side. &x returns the address of x so it satisfies that requirement (even if it is totally redundant). To think about it another way...
cool *y = x;
y->a = 3;
The . operator expects a stack allocated struct on the left hand side. x is that, so x.a works fine.
You can also go the other way, if you have a pointer y you can dereference it with *y and use . on it: (*y).a. This is also totally redundant.
The & prefix operator returns the memory address of whatever object you put it in front of.
This means that you have to put it in front of objects that actually have a memory address. For example, literals and temporary expression results don't necessarily have an address. Variables declared with register storage class don't have an address, either.
Thus:
int i = 5;
&i; // works
&5; // Nope!
&(i + 1); // Nope!
&i + 1; // Works, because &i has higher precedence than +1.
So what does the address of an object give you? It is a pointer to the object. This is how you can do dynamic memory allocation using the heap. This is where functions like malloc() come in. And this is how you can build arbitrarily large data structures.
In C, arrays are represented as pointers. So arrays and pointers are often used interchangeably. For example:
char buffer[100]; // array
strcpy(buffer, "hello"); // strcpy is declared to take (char *, const char *)
The opposite of the address_of operator is the * dereference operator. If I declare a pointer to something, I can get "what it points at" using this syntax:
int i = 5;
int *pi = &i; // pointer to int. Note the * in the declaration?
i + i; // 10
i + *pi; // Also 10, because pi "points to" i
In the case where you have an aggregate type like a struct or union, you would have to do something like this:
struct {
int a;
} s;
s.a = 5;
/* ??? */ ps = &s; // pointer to s
s.a; // 5
(*ps).a; // Also 5, because ps points to s.
ps->a; // 5, because a->b is shorthand for (*a).b
This only works, of course, if you have a pointer to an object that CAN use the .member and that has an appropriately named member. For example, you can't do this:
i = 5;
pi = &i;
pi->a; // WTF? There is no i.a so this cannot work.
If you have a pointer, you can take the address of it. You then have a pointer to a pointer. Sometimes this is an array of pointers, as with the argv array passed to main:
int main(int argc, const char *argv[]);
int main(int argc, const char **argv); // Effectively the same.
You can do weird stuff with pointers to pointers:
int i = 5;
int j = 100;
int * pij;
for (pij = &i; i < j; ) {
if (i & 1) {
*pij *= 2;
pij = &j;
}
else {
i += 1;
*pij -= 1;
pij = &i;
}
}
Note: I have no idea what that code does. But it's the kind of thing you can wind up doing if you're working with pointers.
Maybe I confused people with my example. I was trying to understand a part of the code and simplyfied it. Here is part of the original code (simplyfied again... :)) (see original post below).
uint16_t hal_nrf_read_multibyte_reg(uint8_t *pbuf)
{
uint8_t memtype;
memtype = *(uint8_t*)(&pbuf);
if (memtype == 0x00U)
{
uint8_t data *buf = (uint8_t data *)pbuf;
DOTHIS
}
if (memtype == 0x01U)
{
uint8_t xdata *buf = (uint8_t data *)pbuf;
DOTHAT
}
if (memtype == 0xFEU)
{
uint8_t pdata *buf = (uint8_t data *)pbuf;
DOSOMETHING
}
return SOMETHING;
}
void main()
{
uint8_t payload[3];
hal_nrf_read_multibyte_reg(payload);
while(1) { }
}
So I was wondering, why do they cast pbuf which already is of uint8_t. But I think I've got my answer now.
------------ OLD POST -------------
I'm exploring Nordic Semiconductors nRF24LE1.
If I have the following test code.
void tempF(int *test)
{
int varA;
int varB;
int varC;
varA = *(int*)(&test); // The way it is done in the source code
varB = *(&test);
varC = test;
printf("A: %x\n", varA);
printf("B: %x\n", varB);
printf("C: %x\n", varC);
printf("C1: %x\n", test);
if (test == 0x00)
printf("equals 0x00");
}
int main(void) {
int myArray[3];
tempF(myArray);
return 0;
}
The printfs all give the same reply.
What is the reason for doing it "varA-style"? Examples where it is necessary?
If I use the way in varA I don't get the warning "Warning C260: '=': pointer truncation.
Your three samples are all basically converting a pointer into an int. Technically, this requires a cast in your cases B and C, and your compiler ought to warn you about that. For example:
int varC = (int) test;
With the cast, that is completely valid, but without, not. Nevertheless, your compiler probably produces the same code with or without.
In your example code, however, the type of the expression &test is int **. Casting an expression of that type to int * and dereferencing the result, as is done to assign a value to varA, is intended to have the effect of reinterpreting the bytes of test as those of an int, as with a C++ reinterpret_cast. This does not necessarily produce the same value as converting test directly to an int, as is done to assign a value to varC. They are especially prone to differ if the size of a pointer is not the same as the size of an int on the target system, but they are not required to produce the same result even if the sizes are the same.
On the other hand, applying the * operator directly to the result of the & operator has no net effect, so the value computed for varB will reliably be the same as that computed for varC.
The problem is that any pointer type need not be of same size as an int. The compiler truies to warn you about that fact.
Using (int *)(&test) casts the address of test to be a pointer to int.
Dereferencing this yields an int that happily can be assigned to an int variable. It may still be truncated if pointers need more bits than an int can hold, but you convinvced the compiler that you do know what you are doing and it happens by purpose.
Given that your example varibles are actually int:
int varA;
int varB;
int varC;
Without using the GCC compiler versions 4.4.7 or newer and using stdio.h as noted in comments, the code does not compile, the second two of your statements will error out because of illegal types 'int' and 'pointer to int'
varA = *(int*)(&test); // The way it is done in the source code
varB = *(&test);//error
varC = test; //error
If they were int *
int *varA;
int *varB;
int *varC;
Then the first statement: varA = *(int*)(&test); would error out.
The only way the assignment statements will compile is with the variables declared as follows:
int varA;
int *varB;
int *varC;
varA = *(int*)(&test); // The way it is done in the source code
varB = *(&test);
varC = test;
varA = *(int*)(&test); means interpret the bitwise representation of test as an int, then store it in var.
The cast, (int *), indicates that the bitwise representation of test should be interpreted as an int, while the * operator interprets it as an int.
This is identical to memcpy(&varA, &test, sizeof varA);, if sizeof (int) == sizeof (int *).
In this answer, the author discussed how it was possible to cast pointers in C. I wanted to try this out and constructed this code:
#include <stdio.h>
int main(void) {
char *c;
*c = 10;
int i = *(int*)(c);
printf("%d", i);
return 1;
}
This compiles (with a warning) and when I execute the binary it just outputs bus error: 10. I understand that a char is a smaller size than an int. I also understand from this post that I should expect this error. But I'd really appreciate if someone could clarify on what is going on here. In addition, I'd like to know if there is a correct way to cast the pointers and dereference the int pointer to get 10 (in this example). Thanks!
EDIT: To clarify my intent, if you are worried, I'm just trying to come up with a "working" example of pointer casting. This is just to show that this is allowed and might work in C.
c is uninitialized when you dereference it. That's undefined behaviour.
Likewise, even if c were initialized, your typecast of it to int * and then a dereference would get some number of extra bytes from memory, which is also undefined behaviour.
A working (safe) example that illustrates what you're trying:
int main(void)
{
int i = 10;
int *p = &i;
char c = *(char *)p;
printf("%d\n", c);
return 0;
}
This program will print 10 on a little-endian machine and 0 on a big-endian machine.
These lines of code are problematic. You are writing through a pointer that is uninitialized.
char *c;
*c = 10;
Change to something like this:
char * c = malloc (sizeof (char));
Then, the following line is invalid logic, and the compiler should at least warn you about this:
int i = *(int*)(c);
You are reading an int (probably 4 or 8 bytes) from a pointer that only has one byte of storage (sizeof (char)). You can't read an int worth of bytes from a char memory slot.
First of all your program has undefined behaviour because pointer c was not initialized.
As for the question then you may write simply
int i = *c;
printf("%d", i);
Integral types with rankes less than the rank of type int are promoted to type int in expressions.
I understand that a char is a smaller size than an int. I also understand from this post that I should expect this error. But I'd really appreciate if someone could clarify on what is going on here
Some architectures like SPARC and some MIPS requires strict alignment. Thus if you want to read or write for example a word, it has to be aligned on 4 bytes, e.g. its address is multiple of 4 or the CPU will raise an exception. Other architectures like x86 can handle unaligned access, but with performance cost.
Let's take your code, find all places where things go boom as well as the reason why, and do the minimum to fix them:
#include <stdio.h>
int main(void) {
char *c;
*c = 10;
The preceding line is Undefined Behavior (UB), because c does not point to at least one char-object. So, insert these two lines directly before:
char x;
c = &x;
Lets move on after that fix:
int i = *(int*)(c);
Now this line is bad too.
Let's make our life complicated by assuming you didn't mean the more reasonable implicit widening conversion; int i = c;:
If the implementation defines _Alignof(int) != 1, the cast invokes UB because x is potentially mis-aligned.
If the implementation defines sizeof(int) != 1, the dereferencing invokes UB, because we refer to memory which is not there.
Let's fix both possible issues by changing the lines defining x and assigning its address to c to this:
_Alignas(in) char x[sizeof(int)];
c = x;
Now, reading the dereferenced pointer causes UB, because we treat some memory as if it stored an object of type int, which is not true unless we copied one there from a valid int variable - treating both as buffers of characters - or we last stored an int there.
So, add a store before the read:
*(int*)c = 0;
Moving on...
printf("%d", i);
return 1;
}
To recap, the changed program:
#include <stdio.h>
int main(void) {
char *c;
_Alignas(in) char x[sizeof(int)];
c = x;
*c = 10;
*(int*)c = 0;
int i = *(int*)(c);
printf("%d", i);
return 1;
}
(Used the C11 standard for my fixes.)
Can someone explain why I do not get the value of the variable, but its memory instead?
I need to use void* to point to "unsigned short" values.
As I understand void pointers, their size is unknown and their type is unknown.
Once initialize them however, they are known, right?
Why does my printf statement print the wrong value?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(int a, void *res){
res = &a;
printf("res = %d\n", *(int*)res);
int b;
b = * (int *) res;
printf("b =%d\n", b);
}
int main (int argc, char* argv[])
{
//trial 1
int a = 30;
void *res = (int *)a;
func(a, res);
printf("result = %d\n", (int)res);
//trial 2
unsigned short i = 90;
res = &i;
func(i, res);
printf("result = %d\n", (unsigned short)res);
return 0;
}
The output I get:
res = 30
b =30
result = 30
res = 90
b =90
result = 44974
One thing to keep in mind: C does not guarantee that int will be big enough to hold a pointer (including void*). That cast is not a portable thing/good idea. Use %p to printf a pointer.
Likewise, you're doing a "bad cast" here: void* res = (int*) a is telling the compiler: "I am sure that the value of a is a valid int*, so you should treat it as such." Unless you actually know for a fact that there is an int stored at memory address 30, this is wrong.
Fortunately, you immediately overwrite res with the address of the other a. (You have two vars named a and two named res, the ones in main and the ones in func. The ones in func are copies of the value of the one in main, when you call it there.) Generally speaking, overwriting the value of a parameter to a function is "bad form," but it is technically legal. Personally, I recommend declaring all of your functions' parameters as const 99% of the time (e.g. void func (const int a, const void* res))
Then, you cast res to an unsigned short. I don't think anybody's still running on a 16-bit address-space CPU (well, your Apple II, maybe), so that will definitely corrupt the value of res by truncating it.
In general, in C, typecasts are dangerous. You're overruling the compiler's type system, and saying: "look here, Mr Compiler, I'm the programmer, and I know better than you what I have here. So, you just be quiet and make this happen." Casting from a pointer to a non-pointer type is almost universally wrong. Casting between pointer types is more often wrong than not.
I'd suggest checking out some of the "Related" links down this page to find a good overview of how C types an pointers work, in general. Sometimes it takes reading over a few to really get a grasp on how this stuff goes together.
(unsigned short)res
is a cast on a pointer, res is a memory address, by casting it to an unsigned short, you get the address value as an unsigned short instead of hexadecimal value, to be sure that you are going to get a correct value you can print
*(unsigned short*)res
The first cast (unsigned short*)res makes a cast on void* pointer to a pointer on unsigned short. You can then extract the value inside the memory address res is pointing to by dereferencing it using the *
If you have a void pointer ptr that you know points to an int, in order to access to that int write:
int i = *(int*)ptr;
That is, first cast it to a pointer-to-int with cast operator (int*) and then dereference it to get the pointed-to value.
You are casting the pointer directly to a value type, and although the compiler will happily do it, that's not probably what you want.
A void pointer is used in C as a kind of generic pointer. A void pointer variable can be used to contain the address of any variable type. The problem with a void pointer is once you have assigned an address to the pointer, the information about the type of variable is no longer available for the compiler to check against.
In general, void pointers should be avoided since the type of the variable whose address is in the void pointer is no longer available to the compiler. On the other hand, there are cases where a void pointer is very handy. However it is up to the programmer to know the type of variable whose address is in the void pointer variable and to use it properly.
Much of older C source has C style casts between type pointers and void pointers. This is not necessary with modern compilers and should be avoided.
The size of a void pointer variable is known. What is not known is the size of the variable whose pointer is in the void pointer variable. For instance here are some source examples.
// create several different kinds of variables
int iValue;
char aszString[6];
float fValue;
int *pIvalue = &iValue;
void *pVoid = 0;
int iSize = sizeof(*pIvalue); // get size of what int pointer points to, an int
int vSize = sizeof(*pVoid); // compile error, size of what void pointer points to is unknown
int vSizeVar = sizeof(pVoid); // compiles fine size of void pointer is known
pVoid = &iValue; // put the address of iValue into the void pointer variable
pVoid = &aszString[0]; // put the address of char string into the void pointer variable
pVoid = &fValue; // put the address of float into the void pointer variable
pIvalue = &fValue; // compiler error, address of float into int pointer not allowed
One way that void pointers have been used is by having several different types of structs which are provided as an argument for a function, typically some kind of a dispatching function. Since the interface for the function allows for different pointer types, a void pointer must be used in the argument list. Then the type of variable pointed to is determined by either an additional argument or inspecting the variable pointed to. An example of that type of use of a function would be something like the following. In this case we include an indicator as to the type of the struct in the first member of the various permutations of the struct. As long as all structs that are used with this function have as their first member an int indicating the type of struct, this will work.
struct struct_1 {
int iClass; // struct type indicator. must always be first member of struct
int iValue;
};
struct struct_2 {
int iClass; // struct type indicator. must always be first member of struct
float fValue;
};
void func2 (void *pStruct)
{
struct struct_1 *pStruct_1 = pStruct;
struct struct_2 *pStruct_2 = pStruct;
switch (pStruct_1->iClass) // this works because a struct is a kind of template or pattern for a memory location
{
case 1:
// do things with pStruct_1
break;
case 2:
// do things with pStruct_2
break;
default:
break;
}
}
void xfunc (void)
{
struct struct_1 myStruct_1 = {1, 37};
struct struct_2 myStruct_2 = {2, 755.37f};
func2 (&myStruct_1);
func2 (&myStruct_2);
}
Something like the above has a number of software design problems with the coupling and cohesion so unless you have good reasons for using this approach, it is better to rethink your design. However the C programming language allows you to do this.
There are some cases where the void pointer is necessary. For instance the malloc() function which allocates memory returns a void pointer containing the address of the area that has been allocated (or NULL if the allocation failed). The void pointer in this case allows for a single malloc() function that can return the address of memory for any type of variable. The following shows use of malloc() with various variable types.
void yfunc (void)
{
int *pIvalue = malloc(sizeof(int));
char *paszStr = malloc(sizeof(char)*32);
struct struct_1 *pStruct_1 = malloc (sizeof(*pStruct_1));
struct struct_2 *pStruct_2Array = malloc (sizeof(*pStruct_2Array)*21);
pStruct_1->iClass = 1; pStruct_1->iValue = 23;
func2(pStruct_1); // pStruct_1 is already a pointer so address of is not used
{
int i;
for (i = 0; i < 21; i++) {
pStruct_2Array[i].iClass = 2;
pStruct_2Array[i].fValue = 123.33f;
func2 (&pStruct_2Array[i]); // address of particular array element. could also use func2 (pStruct_2Array + i)
}
}
free(pStruct_1);
free(pStruct_2Array); // free the entire array which was allocated with single malloc()
free(pIvalue);
free(paszStr);
}
If what you want to do is pass the variable a by name and use it, try something like:
void func(int* src)
{
printf( "%d\n", *src );
}
If you get a void* from a library function, and you know its actual type, you should immediately store it in a variable of the right type:
int *ap = calloc( 1, sizeof(int) );
There are a few situations in which you must receive a parameter by reference as a void* and then cast it. The one I’ve run into most often in the real world is a thread procedure. So, you might write something like:
#include <stddef.h>
#include <stdio.h>
#include <pthread.h>
void* thread_proc( void* arg )
{
const int a = *(int*)arg;
/** Alternatively, with no explicit casts:
* const int* const p = arg;
* const int a = *p;
*/
printf( "Daughter thread: %d\n", a );
fflush(stdout); /* If more than one thread outputs, should be atomic. */
return NULL;
}
int main(void)
{
int a = 1;
const pthread_t tid = pthread_create( thread_proc, &a );
pthread_join(tid, NULL);
return EXIT_SUCCESS;
}
If you want to live dangerously, you could pass a uintptr_t value cast to void* and cast it back, but beware of trap representations.
printf("result = %d\n", (int)res); is printing the value of res (a pointer) as a number.
Remember that a pointer is an address in memory, so this will print some random looking 32bit number.
If you wanted to print the value stored at that address then you need (int)*res - although the (int) is unnecessary.
edit: if you want to print the value (ie address) of a pointer then you should use %p it's essentially the same but formats it better and understands if the size of an int and a poitner are different on your platform
void *res = (int *)a;
a is a int but not a ptr, maybe it should be:
void *res = &a;
The size of a void pointer is known; it's the size of an address, so the same size as any other pointer. You are freely converting between an integer and a pointer, and that's dangerous. If you mean to take the address of the variable a, you need to convert its address to a void * with (void *)&a.
I'm trying to better understand c, and I'm having a hard time understanding where I use the * and & characters. And just struct's in general. Here's a bit of code:
void word_not(lc3_word_t *R, lc3_word_t A) {
int *ptr;
*ptr = &R;
&ptr[0] = 1;
printf("this is R at spot 0: %d", ptr[0]);
}
lc3_word_t is a struct defined like this:
struct lc3_word_t__ {
BIT b15;
BIT b14;
BIT b13;
BIT b12;
BIT b11;
BIT b10;
BIT b9;
BIT b8;
BIT b7;
BIT b6;
BIT b5;
BIT b4;
BIT b3;
BIT b2;
BIT b1;
BIT b0;
};
This code doesn't do anything, it compiles but once I run it I get a "Segmentation fault" error. I'm just trying to understand how to read and write to a struct and using pointers. Thanks :)
New Code:
void word_not(lc3_word_t *R, lc3_word_t A) {
int* ptr;
ptr = &R;
ptr->b0 = 1;
printf("this is: %d", ptr->b0);
}
Here's a quick rundown of pointers (as I use them, at least):
int i;
int* p; //I declare pointers with the asterisk next to the type, not the name;
//it's not conventional, but int* seems like the full data type to me.
i = 17; //i now holds the value 17 (obviously)
p = &i; //p now holds the address of i (&x gives you the address of x)
*p = 3; //the thing pointed to by p (in our case, i) now holds the value 3
//the *x operator is sort of the reverse of the &x operator
printf("%i\n", i); //this will print 3, cause we changed the value of i (via *p)
And paired with structs:
typedef struct
{
unsigned char a;
unsigned char r;
unsigned char g;
unsigned char b;
} Color;
Color c;
Color* p;
p = &c; //just like the last code
p->g = 255; //set the 'g' member of the struct to 255
//this works because the compiler knows that Color* p points to a Color
//note that we don't use p[x] to get at the members - that's for arrays
And finally, with arrays:
int a[] = {1, 2, 7, 4};
int* p;
p = a; //note the lack of the & (address of) operator
//we don't need it, as arrays behave like pointers internally
//alternatively, "p = &a[0];" would have given the same result
p[2] = 3; //set that seven back to what it should be
//note the lack of the * (dereference) operator
//we don't need it, as the [] operator dereferences for us
//alternatively, we could have used "*(p+2) = 3;"
Hope this clears some things up - and don't hesitate to ask for more details if there's anything I've left out. Cheers!
I think you are looking for a general tutorial on C (of which there are many). Just check google. The following site has good info that will explain your questions better.
http://www.cplusplus.com/doc/tutorial/pointers/
http://www.cplusplus.com/doc/tutorial/structures/
They will help you with basic syntax and understanding what the operators are and how they work. Note that the site is C++ but the basics are the same in C.
First of all, your second line should be giving you some sort of warning about converting a pointer into an int. The third line I'm surprised compiles at all. Compile at your highest warning level, and heed the warnings.
The * does different things depending on whether it is in a declaration or an expression. In a declaration (like int *ptr or lc3_word_t *R) it just means "this is a pointer."
In an expression (like *ptr = &R) it means to dereference the pointer, which is basically to use the pointed-to value like a regular variable.
The & means "take the address of this." If something is not a pointer, you use it to turn it into a pointer. If something is already a pointer (like R or ptr in your function), you don't need to take the address of it again.
int *ptr;
*ptr = &R;
Here ptr is not initialized. It can point to whatever. Then you dereference it with * and assign it the address of R. That should not compile since &R is of type lc3_word_t** (pointer to pointer), while *ptr is of type int.
&ptr[0] = 1; is not legal either. Here you take the address of ptr[0] and try to assign it 1. This is also illegal since it is an rvalue, but you can think of it that you cannot change the location of the variable ptr[0] since what you're essentially trying to do is changing the address of ptr[0].
Let's step through the code.
First you declare a pointer to int: int *ptr. By the way I like to write it like this int* ptr (with * next to int instead of ptr) to remind myself that pointer is part of the type, i.e. the type of ptr is pointer to int.
Next you assign the value pointed to by ptr to the address of R. * dereferences the pointer (gets the value pointed to) and & gives the address. This is your problem. You've mixed up the types. Assigning the address of R (lc3_word_t**) to *ptr (int) won't work.
Next is &ptr[0] = 1;. This doesn't make a whole lot of sense either. &ptr[0] is the address of the first element of ptr (as an array). I'm guessing you want just the value at the first address, that is ptr[0] or *ptr.