Struct pointer into struct array [duplicate] - c

This question already has answers here:
Why isn't the size of an array parameter the same as within main?
(13 answers)
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 8 years ago.
I can't find any solution to my problem and my brain is almost exploding...
I have defined a struct and a function to create contacts, like a adress book.
I'm asking how many contacts want to be created and this totally works fine.
So I end up with an array of Contacts which pointer i give to my menue.
In my menue I can choose to create a contact, search and delete a contact.
Currently I'm working on searching a contact.
So I start the search function and give it the pointer on my Struct.
I have no clue how to dereference this pointer into an array of structs again.
It's probably just a stupid small little error, but I can't find it.
So I first tried to find out how many Contacts I created.
When I try to print the number of created contacts like this:
void searchContact(struct Contact* ContactArray){
int howManyContacts=sizeof(ContactArray)/sizeof(struct Contact);
printf("%d",howManyContacts);
}
I always get 0 printed out.
Doesn't matter if I create 1,2,3....Contacts
I hope someone of you can help me...It's driving me crazy
By the way, I'm using Eclipse with GCC compiler

Arrays that are passed to a function are treated as pointers, so sizeof(contactArray) will always be the size of a pointer to struct Contact - a constant value. See here for more info.
You should add a parameter to the function called size that will represent the size of the array. It is impossible to otherwise calculate it inside the method.
You can also wrap an array of contacts in another struct, struct Contacts for instance, and include a field specifying the number of contacts.

In your code
int howManyContacts=sizeof(ContactArray)/sizeof(struct Contact);
ContactArray is of type pointer-to-some-type [struct Contact, to be specific]. It will occupy the size of a pointer.
OTOH, struct Contact is a structure. sizeof will give the total size of the individual elements + padding [if any].
In your case, sizeof(ContactArray) [size taken by a pointer variable] is < sizeof(struct Contact) and as sizeof returns size_t [unsigned int], due to the integer division performed in your code, the result you're getting is 0, rightly.

Ok then how can I dereference the pointer that way, that I can use it this way:
printf("%s \n",ContactArray[x].Name);
printf("%s \n",ContactArray[x].Surname);

Your array size is dynamic. sizeof(ContactArray) will return the same as sizeof(void*), because you're dealing with a pointer, not a fixed size array. C doesn't provide a method to determine the size of your array. You need to store the size of the array somewhere and pass it along.

Related

Can someone help me with problem with sorting data structures in C-language [duplicate]

This question already has answers here:
How do I check if a value matches a string
(4 answers)
How do I properly compare strings in C?
(10 answers)
Closed 4 years ago.
So I've been new in structures so i tried to sort it like normal bubble sort but it won't work and also ti gives me error like "assignment with expression to array type"
I just want to sort names of cocktails in reverse way form 'z' to 'a'.
I did rest of the code which works and i got stucked on this sort
I really tried every way I could think of so if someone can help me it would be great.
Thanks :)
typedef struct {
char name[20+1];
char sast1[20+1];
char sast2[20+1];
char sast3[20+1];
} kokteli;
j=i;
int s;
int flag;
char *pom;
while(1) {
flag = 0;
for(s=0; s<j; s++) {
if(k[s].name> k[s+1].name) {
pom = k[s].name;
k[s].name= k[s+1].name;
k[s+1].name= pom;
flag = 1;
}
} if(flag == 0){
break;
}
}
So I've been new in structures so i tried to sort it like normal
bubble sort but it won't work and also ti gives me error like
"assignment with expression to array type"
I won't speak to what your code is actually trying to achieve but I will address the error you are getting. The compiler should be pointing out these two lines:
k[s].name= k[s+1].name;
k[s+1].name= pom;
So for clarity sake let's point out the fact that k is an array of kokteli structs and those structs contain members that are arrays (name, sast1, etc). k[s].name and k[s+1].name are both an array of char which in C is not assignable. You can modify the elements (char) of the array via pointers to the memory address for each char in the array. You would do that like this:
k[s].name[n] = //where n is an integer from 0 to 20, assign value of nth element here)
Let's break this statement down:
k is a pointer to an array of kokteli structs
k[s] is actually a pointer to the address of the kokteli struct located at the memory address offset from k by s (the exact same thing in C as (k+s))
k[s].name is actually a pointer to the address of the member name of the kokteli struct located at offset s (can also be written in C as (k+s)->name or &k[s] //since the first member is name)
k[s].name[0] is the contents of the 0th element of the member name of the kokteli struct located at the memory address offset from k by s (can also be written in C as *(k+s)->name)
This is why the compiler doesn't complain about this line:
pom = k[s].name;
Now the caveat here is that the name of an array in C actually refers to a memory address for the beginning of the contents of that array. This means that it is a pointer itself. So since pom and k[s].name are actually both char *, pom now points to what k[s].name is pointing at.
Your if clause here:
if(k[s].name > k[s+1].name){
...
}
Is actually comparing memory addresses as k[s].name and k[s+1].name both point to the first element in the array. The difference is that one is located at a memory offset that is sizeof(kokteli) greater than the other (that is k[s+1].name) so this statement will never be true. I've made some code for you here that will nail this home.
As other people in the comments have pointed out, you will actually want to use strcmp (need to #include <string.h>) to compare the elements of the two arrays of type char. Reference for strcmp is located here.
So your if clause should look something like this
if(strcmp(k[s].name, k[s+1].name) > 0){
//k[s].name comes after k[s+1].name alphabetically
}
For more on how strcmp works, see this answer.

Dynamically declaring structs not working as expected [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 5 years ago.
I'm having issues with my program, and I'm trying to break it down and I'm seeing that I'm having issues with memory allocation at a minimum.
I have a struct:
typedef struct{
int originX;
int originY;
char ticBoard[3][3];
int result;
int turn;
} simBoard;
I would expect the size of this struct (one single instance of it) to be (4 ints * 4 bytes) + (1 bye char * 3 * 3) or 25 bytes. When I run the sizeof() function on simBoard, I get a value of 28 bytes. I'm assuming that it's the 25 + 3 extra that I don't need to worry about.
The main issue is when I try to declare an array of this struct
simBoard* boardArray = (simBoard*)malloc(sizeof(simBoard)*size));
Assume size is some constant for this scenario. To my knowledge this should create an array of the simBoard struct, of size size. I should be able to go
boardArray[3]
And get the 4th item of boardArray correct? However I'm running into an issue with the memory allocation. When I run:
printf("%zu is the size of the array\n", sizeof(boardArray));
The return value is 8. I even tried to further sort out the issue:
simBoard* boardArray = (simBoard*)malloc(224);
When I ran the printf again, I'm still getting a value of 8 bytes for boardArray. If you guys could lead me in the right direction that'd be fantastic, as I'm absolutely stumped here.
Thank you!
You can indeed index the 4th struct in the array using the notation boardArray[3].
Bear in mind though that boardArray itself is a pointer type. That explains your printf output. Arrays with dynamic storage duration and pointer types are inextricably linked in C. For the avoidance of doubt, sizeof(boardArray) is sizeof(simBoard*).
C doesn't provide functionality to obtain the length of an dynamic array. You need to remember the length yourself.
Don't forget to call free(boardArray) when your done. The C runtime library will take appropriate measures to ensure that all the struct elements are freed.

C Array as function parameter: Size check? [duplicate]

This question already has answers here:
C sizeof a passed array [duplicate]
(7 answers)
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 7 years ago.
I wrote the following function in C:
void dummy(int* my_array, int size)
{
//my implementation
}
Is there any way to check whether size is REALLY the size of my_array?
For example, if I call the function and use for my_array an array with 4 elements but pass 5 for size, is there any way to know that 5 is not really the size of the array?
Thank you in evidence.
You're looking at it the wrong way. An array is contiguous piece of memory. In C, you can represent this concept with a pointer to its start and its size. Since your array is represented by a <my_array, size> tuple, it doesn't make sense to talk about my_array's size, since it's only the start-pointer of the array.
unfortunately, there is no such way in C. As an array is always a pointer to an arbitrary address in memory, there is no such thing as "array bounds" that can be checked.
This is why many of the C functions have that special size parameter: because there's no other way of determining an array's size.
The size of the array is however big you made it when you declared and initialized it.
int my_array[100] = {0}; has a size of 100.
int my_other_array[50] = {0}; has a size of 50.
If you want the length of the data, then you're thinking in more abstract terms than the language can handle. The length of your data is a non-measurable parameter when the language does not support it.
If my_array is dynamically allocated (with malloc) you can get the size of memory block but it depends on specific compiler. Unfortunately in most cases there is address alignments and you will not have the exact size to 1 byte but aligned to 32 bits or other.

Access two-dimensional array via pointer to first element

I got strucure
typedef struct
{char *cells;}
Map;
and cells suppose to be pointer to array of rows(in rows are integers on every position).
I don't know how to access for example to number on 3. position in 2. row.
I have stared with some array[3][3], but I don't know how to connect them with this struct.
I tried
Map nextmap;
nextmap.cells[0] = array[0][0];
But I got only first number, which is clear. How can I get to other positions?
Thanks in advance.
EDIT: renaming the structure ..
.
When you did Map nextmap;, you created an uninitialized Map struct. When you did nextmap.cells[0] = array[0][0]; you dereferenced (i.e. followed) the uninitialized pointer, and stored a value at the random memory it points at.
If you want to initialize the cells structure, you can do something as simple as nextmap.cells = array[0]; That will cause nextmap.cells to point at array. Note that it's not copying the contents; just pointing at them. That means that if you change the values through cells, you'll be modifying the values in arrays.
(Also, using 'new' as a variable name is perfectly acceptable in C, but you're likely to confuse any C++ programmers reading your code, since 'new' is an operator in that language.)
new now changed to nextmap in question
Edited to correct the type mismatch in nextmap.cells assignment.
Given an array char array[][NumberOfColumns] (the first dimension is irrelevant and is omitted here; it would be needed when the array is defined), you can set a pointer to the first element of the array with:
nextmap.cells = &array[0][0];
Then you can access an element in the array, array[i][j], by calculating its position within the array, with either of these two expressions:
*(nextmap.cells + i*NumberOfColumns + j)
nextmap.cells[i*NumberOfColumns + j]
Two-dimensional arrays generally ought to be addressed as two-dimensional arrays. Calculating the position manually is poor practice if done without good reason. If this school assignment did not have a good reason for this, then it is a bad assignment.
First of all new is not a good name for a variable.
new now changed to nextmap in question
Second of all in your case cells should be a double pointer, like this
char ** cells;
Or a pointer to a 2D array, like
char (*cells)[N][N];
where N is a constant you want to use.

How do I use an array variable inside an array of structures?

I'm trying to grasp the concept of arrays of structures and came up with a problem. Hopefully you can help me out.
Okay, so, the problem I'm facing is how to declare and use (i.e. accept & display values) of an array variable within an array of structures?
This sample code may visually help you to understand my problem:
#include<stdio.h>
struct node{
int roll;
char name[10];
int grades[5]; // Accepts 5 grades for each student
};
int main()
{
struct node student[3];
/*Accept and display values for structure members here*/
return 0;
}
I know there's a similar example here.
But I don't understand line 4 in the accepted answer's main() section, where memory is allocated using malloc() :
list[ip].inputs[inp]= (char*)malloc(25);
I'm getting confused between the 25 bytes allocated here and the 10 defined in char* inputs[10];
What exactly is happening here? And how do you solve the problem I mentioned above?
There's an extra * in the example you quote. The malloc is needed only because of that, in your example inputs is an array of 10 pointers to char while here name is a buffer holding 10 chars. You don't need any malloc in your code.
Your structure looks like this in memory (assuming 4-bytes ints):
Your student array from main looks like:
As you see, fields are laid out one after another. Thus, to read the name of the first student you have to write into student[0].name (using strncpy to ensure that there's no overflow). To change the third letter of the name of the second student you'll use student[1].name[2].
You can safely use it like this:
strcpy(student[1].name, "Yu Hao");
student[1].grades[1] = 95;
printf("student 1 name: %s\n", student[1].name);
printf("student1 grades1:%d\n", student[1].grades[1]);
The example you linked uses malloc because the struct has some pointers, and pointers have to point to somewhere valid before using. That's not the case in your example.
Note that using strcpy can lead to disaster when you copy a string longer than 10, if that's to consider, use strncpy instead.
To answer the question related to the referred post.
First, hope you have basic knowledge about pointers in C.
A pointer is indeed a memory address for short.
For details I recomend you this booklet (a very excellent introduction about arrays and poiners).
In that piece of codes, the inputs is defined as char* inputs[10];.
It's an array of pointers.
So each elment in that array should be an address.
The argument 25 in the malloc invokation is not necessary (you can also specify 40 or 50 to meet your requirement).
The only thing you should guarantee is that each element in the array is an address (that's what malloc returns).
The 10 specifies array dimension, i.e. you can store 10 addresses in total in inputs or say, you can initialize the array by invoking malloc ten times like:
struct a;
for (int i = 0; i < 10; i++) {
a.inputs[i] = (char *) malloc(25);
}
Back to your own problem.
In your case, the symbol name identifies the address to the storage.
No need for you to malloc new storage.

Resources