I was asked a question during an C Language interview.
the question is:
int *point;
'0x983234' is a address of memory;//I can not remember exactly
how could we assign 20 to that memory?
it looks likes a embedded programming question, can anyone explains me?
I suspect that it is an embedded programming question, and that you are misremembering it slightly. It was probably something like-
int *point = (int *) 0x983234;
*point = 20;
Embedded programmers do do stuff like that when there is a register that they want to read/write at address 0x983234.
First you have to set your pointer to the right address (so that it points where you need it to).
Then, to write at that address, you dereference the pointer and do assignment. It will look something like this:
int main ()
{
volatile int *point = (int *)0x983234;
*point = 20;
return 0;
}
Please note volatile keyword. It is recommended to use it so that compiler doesn't make any assumptions and optimize it.
If you have larger chunk of data to store, use memcpy or memmove with that address to copy data from/to it, like this:
#include <string.h>
int main ()
{
const char data[] = "some useful stuff";
memcpy ((char *)0x983234, data, sizeof (data));
return 0;
}
I use this approach to do it.its benefit is that you don't need another variable (pointer).
assume that you want to set a variable of type uint8_t at adress 0x00002dbd to 200. you could code simply:
*(uint8_t*)0x00002dbd=200;
or if you a have uint32_t variable (not a pointer) that contains the address of the your uint8_t variable, you can do this:
uint32_t x;
x=0x00002dbd;
*(uint8_t*)x=200;
it doesn't matter what type your target variable is. just the type instead of uint8_t part.
Related
For an embedded system project, an array is supposed to be placed in RAM. I have split the device's RAM into two sections, one which stores globals and other data, and another section, RAM_DATA, which I wish to store two arrays (a source location and a destination location).
There is a global value mem_val that is set to the start of the RAM_DATA address, and now wanted to make the source array begin at the location which is stored held in location.
From what I have garnered from online sources, they utilize the stdint.h header file to use uintptr_t and uint32_t values to set start of the array. When debugging the program, the array does not start at this value, and was inquiring about how to fix this problem. Here is some code that is relevant to the question.
volatile uintptr_t mem_val = 0x0219;
int main(void)
{
char cur_loc[128];
uint32_t *cur_loc = (void *)mem_val;
...
return 0;
}
Obviously there is something wrong with the array initialization and then making it pointer, but beyond that, is there a method of making the array cur_loc begin at the value given to mem_val? If it helps, I am working with a Texas Instruments MSP430 embedded device. Thank you
There were some valuable remarks concerning the MSP430. Here, my two cents concerning the array at a specified memory location:
volatile uintptr_t mem_val = 0x0219;: If I got it right the address shall be "burnt" into binary. Hence volatile doesn't make sense but const would:
const uintptr_t mem_val = 0x0219;`
Instead, (assuming the fix address is in an I/O range mapped into address space) it makes much more sense to mark the contents of array/pointer as volatile:
volatile uint32_t *cur_loc = (void*)mem_val;
The below is a "duplicate symbol error":
char cur_loc[128];
uint32_t *cur_loc = (void *)mem_val;
Actually, the 2nd line is fully sufficient as pointers can be used like arrays. C hasn't any bound checking per standard. Hence, the pointer to uint32_t can be used like an array of uint32_t elements.
With some extra parentheses, it is even possible to set the address of an array:
volatile uint32_t (*curLoc)[128 / sizeof (uint32_t)] = (void*)mem_val;
But, to access the array the "contents" operator has to be used always: (*curLoc)[i]. Not to mention, that the parentheses are essential (*curLoc[i] does it wrong).
So, I made a little sample (for 3. as "counter-example" and to practice my C-typing abilities):
#include <stdint.h>
#include <stdio.h>
int main()
{
char storage[32] = {
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f'
};
const uintptr_t mem_val
= (uintptr_t)&storage; /* 0x0219 <- a fix address wouldn't work on wandbox. */
enum { size = sizeof storage / sizeof (uint32_t) };
printf("size: %u\n", size);
/* using pointer */
volatile uint32_t *pCurLoc = (uint32_t*)mem_val;
for (unsigned i = 0; i < size; ++i) printf(" %08x", pCurLoc[i]);
puts("");
/* using array */
volatile uint32_t (*curLoc)[size] = (void*)mem_val;
for (unsigned i = 0; i < size; ++i) printf(" %08x", (*curLoc)[i]);
puts("");
/* done */
return 0;
}
Output:
size: 8
03020100 07060504 0b0a0908 0f0e0d0c 13121110 17161514 1b1a1918 1f1e1d1c
03020100 07060504 0b0a0908 0f0e0d0c 13121110 17161514 1b1a1918 1f1e1d1c
Live Demo on wandbox
I am working on one Embedded C project. I am having trouble understanding the use of array and structure in code.
for example:
Structure:
struct example_struct{
char a;
char b;
char array[4];
}
Note: The default size for Int and char is 1 byte.
The compiler I am using provide the functionality of memory allocation for variables and other parameters using '#' symbol
for example:
Memory Allocation
int example # 0x125
// Compiler allocate the RAM memory location 0x125 to my variable "example"
Issue:
The person who coded this project have used the structure and array as given below
example.h
struct example_struct{
char a;
char b;
char array[4];
}
Memory.h
volatile struct example_struct node # 0x130 ;
//allocate memory location 0x130 - 0x135 to node
volatile char buffer[6] # 0x130;
//allocate memory location 0x130 - 0x135 to buffer
Question
1.Instead of using the pointer to access the member of structure is it appropriate to use the array placed on same memory location?
Does it cause the memory issue?
Would you please help me to understand the use of stuct and array in this particular situation.
Thank you
Kunal
The (weird) coder that developed that code was "simulating" an union to be able to access the same location as struct example_struct or byte per byte.
Like:
#pragma pack(1)
union struct_and_raw_byte_access
{
struct example_struct
{
char a;
char b;
char array[4];
}structured;
char buffer[sizeof(struct example_struct)];
};
#pragma pack()
int main(void)
{
union struct_ad_raw_byte_access temp;
int i;
temp.structured.a = 1;
temp.structured.b = 2;
temp.structured.array[0] = 3;
temp.structured.array[1] = 4;
temp.structured.array[2] = 5;
temp.structured.array[3] = 6;
for (i=0; i< sizeof(temp.buffer)/sizeof(temp.buffer[0]); i++)
printf("buffer[%d] = %d\n", i, temp.buffer[i]);
return 0;
}
1.Instead of using the pointer to access the member of structure is it appropriate to use the array placed on same memory location?
2.Does it cause the memory issue?
IMHO you cannot do that. It may work in some archs, but keep in mind that you are trusting the compiler to put everything packed and aligned.
Some compilers have packing directives (pragmas or parameteres), but it is much more safer to use an union.
Make sure that buffer is also a pointer, so allocating "buffer" to absolute address is the same like make a pointer to that address.
volatile char buffer[6] # 0x130;
//allocate memory location 0x130 - 0x135 to buffer
In your case, developer; I think; he decided to access strcutre elements using array for work with them in loop or something.
So, answering your questions:
No, It is not appropriate, as you said, it is better to make pointer and access this pointer by casting it to (char *)
If you know how you will use "buffer", no memory issue will happen. I mean make sure no out of index will happen.
Your comment "if I am declaring any global variable and watching it using debugger I can see the change in value. Even if I am not using them anywhere" probably means that you are looking at a hardware register of some IO controller.
The
volatile char buffer[6] # 0x130;
Is intended to map those IO controller addresses to a variable name in your embedded programming. That is the IO controller is presenting status and data at memory address 0x130 to 0x135 -- and the C program maps this to a symbolic value through the declaration.
Since the format of this area is determined by the IO controller (nothing you can do in your C code will change the format), you need to make sure that the strct and the example_struct is exactly 6 bytes long, or if not you have some padding which will kill you.
Test this using your debugger (if it is gdb use can use sizeof, but your debugger may differ)
Also, I recommend that you find some kind of documentation on what is on hardware address 0x130
EDIT: Thank you very much for your responses. I understand this properly now!
I am trying to learn more on C pointers. Tinkering around, I am questioning the difference between two actions I am using.
This code seems to work at first glance, but I am not sure of what's the difference, and if any of these two approaches is wrong in some way.
I'd like to know what's the difference between the two pieces of code, when I should I pass the adress, and when a pointer to an array?
Is any of the pieces wrong? If so, what would be the proper way?
having a simple struct grid pretty much like struct grid { int val; } (for demonstration purposes)
First piece of code. Passing address of the pointer to the array.
void set (mygrid *grid, int foo){
grid->bar = foo; //should this be '*grid->bar?' But this seems to work properly.
}
void main(){
int i;
int* array;
int max = 24;
array = malloc(sizeof(grid) * max);
for(i = 0; i < max; i++){
set(&array[i], 0);
}
}
Second piece of code. I am not entirely sure why this works, but the compiler doesn't output any warning.
I am supposed to be passing the pointer to the start of the array like this?
void set(mygrid *grid, int foo){
int i; int max = 24; //so this example code compiles :P
for(i = 0; i < max; i++){
grid[i].bar = foo;
}
}
void main(){
int* array;
int max = 24;
array = malloc(sizeof(grid) * max);
set(array, 0); //Why not &array?
}
Passing an array decays into a pointer that points to the first member of the array, just like &array[0].
In your second example, array is just a pointer, and the return value from malloc is just the address of the start of the block of memory you get.
It doesn't have to be used for an array; it could be used for storage of an arbitrary sizeof(int) * max bytes of data. An array (in C) is really just a nice way of thinking about & working with a solid block of memory divided up into equal size portions.
Secondly, you should understand how my_array[i] works. All it does is take the address of where your block of array data starts (which is the actual value of my_array), and then look at what value is stored at a particular offset from there. Specifically, if my_array is of a (made up) type of WhatEver, then it will access the data from my_array + i*sizeof(WhatEver) to my_array + (i+1)*sizeof(WhatEver).
On a related note (since you're learning C), it's highly recommended to check that the return from malloc is not NULL before doing anything with it.
I'm no C guru but am also trying to improve my understanding so if this is incorrect, please leave a comment or edit my answer so I can learn from my mistakes :)
In your first piece of code
grid->bar is same as (*grid).bar
. and using name of an array refers to its base address. so writing array is equivalent &array[0]
&array[i] is equivalent to array+i
array[i] is equivalent to *(array +i)
In you second piece of code i dont understand why there is no error because in your function set you do not declare max and i dont see a global max variable too.
also in your second piece of code you use
set(array,0) because array is already an integer pointer(see the declaration int * array).As far as i understand the mygrid is not a struct but is an array of structs in the second example
In C, an array is pretty much the same as a pointer. For me this isn't so amazing, since it is one of the earlier programming languages I learned, but if you're coming from a high level language where an array is a different type of object, then it might come across as strange.
I'm trying to create a linked list where you can update the data in a node, but no matter what I try, C doesn't seem to allow me to update the value of a void pointer (or rather where it points to). Here's the test code I have:
void newData(void * d)
{
char data[] = "world";
d = &data;
}
int main()
{
char testData[] = "hello";
void * testPointer = &testData;
printf("TestData is %s\n", (char *)testPointer);
// Modify the data
newData(&testPointer);
printf("TestData is %s\n", (char *)testPointer);
}
Which just outputs::
TestData is hello
TestData is hello
Am I missing something obvious here? I've also tried using a pointer to a pointer, but to no avail.
I think you need
void newData(void ** d)
{
char data[] = "world";
*d = &data;
}
However, this has it's own problems, as "world" is stack local, and won't be valid after you return from newData.
Two things are wrong with this:
char data[] = "world";
Is probably created as part of the function's stack frame. Arrays degrade to pointers. As such, when function calls ret, it should have cleaned up its stack and the memory at that address is gone. If any operation works here, it is because you haven't overwritten the memory yet.
What could you do? Declare it static is one solution that guarantees (according to c99 at least) program-lifetime existence (i.e. it won't be allocated on the stack but in the data segment, and the c library allocates it for you before main). However, since I suspect this is just a demo, it is worth pointing out that:
char data[] = "world";
memcpy(d, data, 5);
Is perfectly valid, since you're copying contents and not pointing to values.
newData(&testPointer);
You're making a simple mistake here. A pointer, in assembly is a memory address holding another memory address. When you pass a pointer to a function, you want to pass that memory address, so that when you call that function the contents of the pointer, a memory address, are copied onto the stack in the form of a new pointer. Of course, both these pointers point to the same thing, which is how you end up achieving a pass-by-reference type thing. If you don't believe me, watch it in a debugger.
However, what you're doing is passing the address of a pointer, so you are creating a pointer to a pointer to a value. Imagine the memory like this:
|Address|Value
|0x120 |0x121 <-- this is what you're passing with &testPointer
|0x121 |0x122 <-- this is a pointer; it contains the address of a value
|0x122 |h <-- this is a value.
|0x123 |e
|0x124 |l
...
I hope that makes it clearer. In my simplistic memory, you're passing 0x120 rather than 0x121. You can of course dereference twice, but why? The simple solution is just to pass the pointer like this:
newData(testPointer);
I think a little change is the code can solve the problem:
void newData(void ** d)
{
char* data = "world";
*d = data;
}
How should I write my code to example a specific array index of an array that happens to be a member of a structure? The following code is giving me problems.
// main.c
void clean_buffers(void); // prototype
struct DEV_STATUS {
unsigned char ADDR;
unsigned char DEV_HAS_DATA;
unsigned char ETH_HAS_DATA;
unsigned char DATA[20];
};
struct DEV_STATUS g_cmdQueue[60] = {0};
void main(void) {
clean_buffers();
while (1) {
;// MCU tasks
}
}
void clean_buffers(void) {
unsigned char theCount = 0;
byte queIdx;
for (queIdx = 0; queIdx < 59; queIdx++) {
struct DEV_STATUS *p_struct;
unsigned char *p_data;
p_struct = &g_cmdQueue[queIdx];
p_data = &p_struct->DATA;
p_struct->ADDR = 0;
p_struct->DEV_HAS_DATA = 0;
p_struct->ETH_HAS_DATA = 0;
theCount = 0;
while(*(p_data+theCount) != 0) {
*(p_data+(theCount++)) = 0;
}
}
} // EOF main.c
I get a compiler error "struct/union member expected" on the following line:
p_data = &p_struct->DATA;
How should I write a pointer if I was to access, for example, the specific value of structure member DATA[3]? I'm confused, I thought that as p_data = &p_struct->DATA; is defined, I should be able to get it by using *(pdata+3) but I guess I'm missing something.
Are you sure you are compiling the same code you posted here?
If your compiler complains at this line
p_data = &p_struct->DATA;
with a "struct/union member expected" message, your compiler is probably broken.
Note, that &p_struct->DATA is a perfectly valid expression in C. There's absolutely no problems with this expression by itself.
The problem here is just that this is not what you need in your case. &p_struct->DATA returns a pointer to the entire array 'DATA', i.e a pointer of type unsigned char (*)[20]. You are trying to assign this value to a pointer of type unsigned char *. This is illegal in C, since the types are completely different, but traditionally C compilers responded to it with a mere "type mismatch" warning and performed an implicit conversion (which, BTW, means that your original code, albeit "dirty", should still work as intended).
Even if some compiler decides to flag this mismatch as an error (which is fine), it still should not complain about any problems of "struct/union member expected" kind. There's no such problems here.
P.S. As other already said, what you really need is p_data = &p_struct->DATA[0], but that still does not explain your compiler's strange behavior. Could it be that 'DATA' is a macro defined somewhere before the 'clean_buffers' definition?
Added 10/19/2009: Nate, in your code you access your array using an index theCount. Since you are using the index access anyway, there's really no reason to even create the pointer you are trying to create. The code will work perfectly fine without any additional pointer, just acess the DATA field directly
theCount = 0;
while (p_struct->DATA[theCount] != 0) {
p_struct->DATA[theCount++] = 0;
(I'd probably use a for cycle here).
If you really insist on creating this pointer and still using the index access, the code should look something like the following (the others already suggested that more than once)
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
theCount = 0;
while (p_data[theCount] != 0) {
p_data[theCount++] = 0;
Moreover, you can opt for a more "exotic" variant :)
unsigned char (*p_data)[20]; /* <- note: declared differently */
...
p_data = &p_struct->DATA; /* <- note: your original version */
...
theCount = 0;
while ((*p_data)[theCount] != 0) {
(*p_data)[theCount++] = 0;
However, returning to a unsigned char *p_data version, since you create that pointer, it might make more sense to use a "sliding pointer" technique instead of using index access
unsigned char *p_data;
...
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
while (*p_data != 0) {
*p_data++ = 0;
As always, it is all a matter of personal preference. Of course, nothing of this will work until you get rid of that interference from the macro.
Lose the & in
p_data = &p_struct->DATA;
p_struct is already a pointer. Afterwards, use p_data[] to access your array.
What you should write is one of two things:
p_data = p_struct->DATA; // DATA is the address of the first element.
OR
p_data = &p_struct->DATA[0]; // taking the address of the first element.
Simply remove the & at the beginning, like this:
p_data = p_struct->DATA;
That is special sintax for arrays (remember they are passed always as reference) and it is equivalent to:
p_data = &p_struct->DATA[0];
And yes, now you can use *(pdata+3)
Hope it helps.
Oops! Thank you AndreyT
struct DEV_STATUS *p_struct;
unsigned char *p_data;
p_struct = &g_cmdQueue[queIdx];
p_data = &p_struct->DATA;
p_struct is a pointer to struct DEV_STATUS.
&p_struct is the address of a pointer to struct DEV_STATUS (or a pointer to a pointer to a struct DEV_STATUS).
You probably want to change that line to
p_data = p_struct->DATA;
Oh ... your clean_buffers() function does not "clean" the element g_cmdQueue[59].
And, because it is a global object, the array g_cmdQueue is initialized to all zeros even before the first statement of main() exceutes.