Setting the starting memory address of a 2d array in C? - c

I have a 2 dimensional array of structures, like so:
struct foo {
int bar;
float baz;
};
I'm actually learning about OS development right now, and one thing I'm trying to do is created a 2d array of these structures with the dimensions 80x25:
struct foo foobar[80][25];
Though I need to set it to the address 0xb8000, since this is where the video memory starts. Is there any way I can specify the address in which my array starts?
So far I have tried doing this:
struct foo foobar[80][25];
*foobar = (struct foo) 0xb8000;
But this doesn't work. Edit: also, is doing something like this legal and/or possible to the c99 standard?

You cannot declare array at a specific location, but you can use a pointer:
struct foo *x;
x = (struct foo*)0xb8000;
This should work, but probably the operating system will complain if you tried that from a normal program, unless it is DOS or something like that.

Related

Is there a principle for choosing between embedding a struct itself or the pointer to a struct inside a struct?

This is a code snippet from qemu.(qemu-5.1.0 include/hw/arm/smmu-common.h)
typedef struct SMMUDevice {
void *smmu;
PCIBus *bus;
int devfn;
IOMMUMemoryRegion iommu;
AddressSpace as;
uint32_t cfg_cache_hits;
uint32_t cfg_cache_misses;
QLIST_ENTRY(SMMUDevice) next;
} SMMUDevice;
I've seen many such codes until now but I am now curious if there is any principle/rule in choosing between
embedding a struct A inside a struct B
embedding a pointer to the struct A inside a struct B
Two things that come to my mind right away is that if a struct A is to be shared by many structs, it is better to use pointer. or if the struct containing the struct(that is, struct B) is to be frequently passed as a function argument, it would be better to use pointer(pointer to struct B as argument, or pointer to A inside struct B and struct B is the argument) because copying the struct to stack would take long time.
I am curious if there are other important rules.
There's no correct answer because it depends on what you want to use them for. Storing a struct inside another struct is generally more efficient, since it gives faster access and better data cache use.
However, it isn't as flexible. If you wish to swap out the whole contents of a big struct for something else, it goes much faster to just swap two pointers than doing a hard copy of all the data. Pointers also enable different forms of allocation - you could have a static storage struct with a pointer at dynamically allocated memory for example.
if a struct A is to be shared by many structs, it is better to use pointer
I don't see how that matters at all. It's just a . vs -> notation by the code using it.
or if the struct containing the struct(that is, struct B) is to be frequently passed as a function argument, it would be better to use pointer
No that's nonsense, you'd always pass the outer struct through a pointer no matter what members it got. Passing it by value doesn't make any sense in either scenario.

Significance of array with only one element

I have come across an array with only one element. This array is defined inside a structure. Which goes like this:
typedef struct abc
{
int variable1;
char variable2;
float array[1];
};
I don't understand why this array is required, why can't we define just a variable or define a pointer(considering array property).
I want to use it. How do i use this variable? abc.array[0] seems correct. Isn't it.
Addition I am not using any dynamic memory allocation then what is its significance ?
It's probably what is called the "struct hack". By allocating a large block of memory, the array becomes dynamic. The one element is just a placeholder to make it compile, in fact there will be many floats.
The dynamic array has to be the last element.
Use like this:
struct abc *ptr = malloc(sizeof(struct abc) + (N-1) * sizeof(float));
ptr->variable1 = N; /* usually store length somewhere in struct*/

Why use address of first element of struct, rather than struct itself?

I've just come upon yet another code base at work where developers consistently use the address of the first element of structs when copying/comparing/setting, rather than the struct itself. Here's a simple example.
First there's a struct type:
typedef struct {
int a;
int b;
} foo_t;
Then there's a function that makes a copy of such a struct:
void bar(foo_t *inp)
{
foo_t l;
...
memcpy(&l.a, &inp->a, sizeof(foo_t));
...
}
I wouldn't myself write a call to memcpy in that way and I started out with suspecting that the original developers simply didn't quite grasp pointers and structs in C. However, now I've seen this in two unrelated code bases, with no common developers so I'm starting to doubt myself.
Why would one want to use this style?
Nobody should do that.
If you rearrange struct members you are in trouble.
Instead of that:
memcpy(&l.a, &inp->a, sizeof(foo_t));
you can do that:
memcpy(&l, inp, sizeof(foo_t));
While it can be dangerous and misleading, both statements actually do the same thing here as C guarantees there is no padding before the first structure member.
But the best is just to copy the structure objects using a simple assignment operator:
l = *inp;
Why would one want to use this style?
My guess: ignorance or bad discipline.
One wouldn't. If you ever moved a in the struct or you inserted member(s) before it, you would introduce a memory smashing bug.
This code is unsafe because rearranging the members of the struct can result in the memcpy accessing beyond the bounds of the struct if member a is no longer the first member.
However, it's conceivable that members are intentionally ordered within the struct and programmer only wants to copy a subset of them, beginning with member a and running until the end of the struct. If that's the case then the code can be made safe with the following change:
memcpy(&l.a, &inp->a, sizeof(foo_t) - offsetof(foo_t, a));
Now the struct members may be rearranged into any order and this memcpy will never go out of bounds.
Actually, there is one legitimate use case for this: constructing a class hierarchy.
When treating structs as a class instances, the first member (i.e. offset 0) will typically be the supertype instance... if a supertype exists. This allows a simple cast to move between using the subtype vs. the supertype. Very useful.
On Darren Stone's note about intention, this is expected when executing OO in the C language.
In any other case, I would suggest avoiding this pattern and accessing the member directly instead, for reasons already cited.
It's a really bad habit. The struct might have another member prepended, for example. This is an insanely careless habit and I am surprised to read that anyone would do this.
Others have already noted these; the one that bugs me is this:
struct Foo rgFoo [3];
struct Foo *pfoo = &rgFoo [0];
instead of
struct Foo *pfoo = rgfoo;
Why deref the array by index and then take the address again? It's already the address, the only difference of note is that pfoo is technically
struct Foo *const,
not
struct Foo *.
Yet I used to see the first one all the time.

C - transferring information to a struct (specifically an array of strings)

This seems to be a very simple problem but I can't quite figure out which part is causing it. Basically, I have a struct that just contains an array of strings
struct command_stream{
char **tokens;
};
typedef struct command_stream *command_stream_t;
command_stream_t test;
Then later on, I parse some strings into shorter ones and end up with another array of strings
char **words = *array of strings*
words contains the correct information I want, I looped through and printed out each element to make sure I wasn't getting a faulty string. So now I just point tokens to words
test->tokens = words;
But it gives me a segmentation fault. I'm not sure why though. They're both pointers, so unless I'm missing something obvious...
EDIT: The function as a whole has to return a pointer, which is why it was set up like this, which I keep forgetting. But I think I've got it, if I just create a new typedef
typedef struct command_stream command_stream_s;
command_stream_s new_command_stream;
and just return
&new_command_stream;
That should work right? Even though new_command_stream itself isn't a pointer.
From your code excerpt, it seems that you have not declared the struct. You have successfully declared a pointer to the struct command_stream_t test; but this pointer does not point to anywhere yet.
You need to allocate memory for your struct in some way and make test reference it. For instance:
command_stream_t test =
(command_stream_t) malloc(sizeof(struct command_stream));
This way you can successfully use:
test->tokens = words;
as you intended.
Note that you don't need to use malloc to allocate the memory. The pointer can reference a local/global variable as long as it has memory associated to it (N.B. if you use a local var don't use the pointer outside the declaration scope of that var).
typedef struct command_stream *command_stream_t;
command_stream_t test;
This makes "test" a pointer. There is no memory allocated for the structure.
You need to allocate memory for the structure and make the test pointer point to the block of memory before you can dereference by saying -
test->tokens = words;
Do this:
typedef struct command_stream command_stream_t;
command_stream_t test;
test.tokens = words;
The difference is that, command_stream_t is no more a pointer type, it is the actual structure.

Simple question on C: Copying variables of user defined struct type

This ought to simple. Say we have a struct from a library that doesn't offer copying facilities. Is there an easy way to copy a variable of the type of that struct to a new variable of the same type without doing assignments for each of its sub members? Or does one have to be making special copying functions?
Well, struct types are assignable in C:
struct SomeStruct s, d;
...
d = s;
It doesn't matter, where they are defined. And there's no need to copy "each of the sub members". Where did you even get the idea about copying it member by member?
Of course, the assignment will perform shallow copying only. If you need deep copying, you need a library-provided copying routine. If there's none, you will have to implement it yourself. In order to do that you will need full knowledge of the actual deep-memory organization of the structure. If you don't know it (i.e. if it is not documented), you are out of luck - proper deep-copying is impossible.
This sounds like the classic deep copy vs shallow copy topic.
You could copy the variable (shallow copy) with a memcpy operation.
If the struct holds references to other varibles, then this might not be enough and you should implement a more sofisticated (deep) copy.
C supports struct assignment natively, so if a per-member copy is safe/effective, you can just use direct assignment:
typedef struct {
int v1, v2;
float f1;
} A;
A a = { 0, 2, 1.5f };
A b;
b = a;
It has already been explained that one may use simple assignment for structs, but perhaps an interesting characteristic of this technique is that it even allows you to copy structs containing arrays despite arrays being unassignable. More importantly, it demonstrates that it is not always possible to copy a struct just by assigning to its members individually.
For example:
typedef struct {
char data[100];
} string;
string a = {"Hello world!"};
string b;
b = a; // works!
puts(b.data); // writes "Hello world!" to standard out.
b.data = a.data; // oops, doesn't work!
Keep in mind that it might not be safe to do per-member copy of a structure; for instance, it may hold pointers, and just copying those pointers might not be a great idea if you want an actual copy of the data. However, when it is safe to do it, you may use memcpy save yourself some keystrokes.
struct foo a, b;
// let the third-party lib fill the struct
thirdPartyLibraryCallInvolvingTheFooStruct(&a);
// now we want to copy a to b
memcpy(&b, &a, sizeof b);
Don't forget to read the manpage for more infos!
You could use the memcpy function. This sets a contiguous area of memory, just copying bit for bit; ignoring whether it's a series of ints, or a char array, or whatever.

Resources