I have a structure comprised of an array of pointers to other structures of a different type.
typedef struct{
NodeT* nodes[2];
int size;
}stackT;
with:
typedef struct{
char info;
}NodeT;
And I have a pointer to the above (first) structure:
stackT* stackPtr;
Assuming the memory is allocated for the stackT structure as well as both NodeT structures with associated assignments for the members of both NodeT structures, how would I pass to a function one of the pointers in stackT?
For example:
void setChar(NodeT* nodePtr, char setTo){
nodePtr->info = setTo;
}
called with line:
setChar(stackPtr->nodes[0], 'A');
Does not work. I figured it had something to do with the -> syntax dereferencing the pointer whereby I am actually passing in a structure. I do not get any compilation errors, but when I check for the assignment by printing whatever is stored in char info I do not get anything.
Is the notation incorrect or do I have issues elsewhere in the program perhaps? I just wanted to rule this out first (proper passing syntax).
If someone is looking for a solution to this problem, the above code was actually correct.
Assuming you have an array of pointer in some structure and you wish to pass such a pointer, the correct syntax would be:
someFunc( structPtr->ptrArray[0] )
The line:
structPtr->ptrArray[0]
Actually returns a pointer, and not whatever the pointer is pointer to.
(*structPtr).ptrArray[0]
Is also equivalent.
That being said, I either mistakenly interpreted the information before me, or I had underlying errors elsewhere in the my code.
Related
Edit:
(1) Title (- previous title: How can I assign the address of a pointer to an already-existing variable? -- resolve at bottom of message);
(2) 'In short';
(3) spelling / punctuation.
In short: I am trying create and then locate a struct on the heap (I want to save memory on the stack), and passing arguments into various functions to populate the struct. In previous projects I created a pointer to struct, allocated this on the heap using malloc, and finally passing the pointer as argument to functions - this worked perfectly. My question: can the same be done without the use of a pointer?
I am trying to store a struct in dynamic memory. I succeeded in a previous mini-project, but I used pointer-to-struct, and passed this pointer to all my functions. Now I am burning to know if I could simply omit passing the pointer and pass the variable struct itself into the function.
My current example
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
typedef struct s_text t_text;
typedef struct s_text
{
int letters;
// some more stuff
} t_text;
int main(void)
{
t_text text;
t_text *tp;
tp = malloc(sizeof(t_text));
//&text = tp; <-- this here I tried, but error (value required as left operand of assignment)
return (0);
}
In the above code I allocate memory on the heap for the tp. This is the memory I'd like to use.
Now, on the stack, memory was reserved for (t_text) text. I would like to discard this and only use the heap.
t_text &text = malloc(sizeof(t_text)); <-- this may work in C++, i don't know, but in C definitely not.
In another post's discussion on NULL pointers, someone claimed in C++ that the address of a variable could point to NULL with the following code
int &x = *(int*)0;
but this definitely is not appreciated by my compiler. In fact, I tried several things with the address of a variable, but each time I try to set eg &text = (some address) this error pops up:
error: lvalue required as left operand of assignment.
(link to the post I refered to: ttps://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable/57492#57492 )
Below what I tried earlier (and works perfectly):
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
typedef struct s_text t_text;
void fn_prompt_user(t_text *tp);
void fn_calc_letters(t_text *tp);
typedef struct s_text
{
int letters;
// some more stuff
} t_text;
int main(void)
{
t_text *tp;
tp = malloc(sizeof(t_text));
fn_prompt_user(tp);
fn_calc_letters(tp);
return (0);
}
To conclude this post with my question: Is there a way I can pass a struct variable
as an argument to a function, or should I just accept passing pointer-to-struct is the one and only way to go?
Thanks!
-- answer to previous title's question (How can I assign the address of a pointer to an already-existing variable?): Not possible.
Error: error: lvalue required as left operand of assignment.
When declaring a variable, it is placed in memory. This memory location can not be changed, and so if int a = 3; a is an lvalue (location value) which can be changed (to eg. 4), but &a is unchangeable, therefor an rvalue (so is 3). So &a = ptr_a; will never work. Thanks for the clarification.
You can pass a struct to a function, like ....
int myfunc(t_text mytext) {....}
then ...
t_text thistext;
...
myfunc(thistext);
and this puts the entire struct onto the stack for the subroutine to use.
but the C language has no 'ref' feature like C++.
You can ...
tp = (t_text *)malloc(sizeof(t_text));
myfunc(*tp);
==
Your second example, passing pointers to objects, is a very conventional means of using structs in C. It has the advantage of not needlessly copying structs to the stack, merely pointers. It has the disadvantage of allowing functions to modify the objects that are pointed to. The latter problem can be remedied by declaring that the argument points to a const struct. Like:
void fn_promt_user(const t_text *tp) {...}
should I just accept passing pointer-to-struct is the one and only way to go?
Basically, yes.
C does not have "pass by reference" built into the language. If you want to have a function populate or otherwise modify a struct for you (or any other object for that matter), passing a pointer is the normal and idiomatic way of doing that. There is no real alternative, short of ugly macro hacks and stuff like that.
This is my first post here. I tried to find a similar question but couldn't find any and hence I am posting this question.
I am trying to copy the data in a structure pointer to another structure pointer in C as shown below. Looks like using just an '=' did the trick. Could someone please explain how the data in pointer srcStruct got copied to another memory location (pointer by destStruct) without using memcpy()?
Is this a pointer property? or is there any risk in doing this?
struct myTestStruct
{
short variable1;
short variable2;
};
struct myTestStruct *destStruct = (struct myTestStruct *)malloc(sizeof(struct myTestStruct));
struct myTestStruct *srcStruct = (struct myTestStruct *)malloc(sizeof(struct myTestStruct));
srcStruct->variable1 = 11;
srcStruct->variable2 = 12;
*destStruct = *srcStruct;
Thanks in advance.
Regards,
AJK
By using the dereferencing operator *, you are basically treating the data that the pointers point to as regular variables. Structs are copied by value, not by reference, if you aren't copying the pointer, so it's just like copying an int to another int. You are essentially doing the following by using the dereference operator *:
struct myTestStruct destStruct, srcStruct;
srcStruct.variable1 = 11;
destStruct = srcStruct; //this gets copied by value
What you're doing here isn't actually connected to pointers at all; it's a property of structs in general in C that they can be assigned as a whole unit with a single = operation. When you dereference a pointer you're using the pointed-to value directly in the expression, so what you've really got there, with a dereference on both sides, is an assignment from a value struct to another value struct. The pointers have both been "expanded out", leaving the values of the whole structs themselves.
How the value is copied is up to the compiler. It will likely emit custom instructions to do it in the most efficient possible way, but it could also use memcpy if it wanted to. There is absolutely no risk in doing this - structs being assignable is a core element of the C language and not going away! It is perfectly idiomatic, and usually the best way to do whatever you're doing that needs data copied from one struct to another. Certainly better than invoking memcpy unnecessarily.
I made a linked list whose nodes hold 4 string values. When I call the newNode function, an error says 'Node has no member named familyName', as well as the other members. My code:
I am really confused with how strings work in structs.
Your immediate problem is the type definition. You cannot call malloc() from within there, all you can do is define the fields. The memory allocation must come later. So, it should be:
typedef struct node{
char *familyName;
char *firstName;
char *address;
char *phoneNumber;
struct node *link;
}Node;
You'll strike another problem (run-time rather than compile-time) once you fix that. When you do something like:
p -> familyName = famName;
that simply copies the pointer into your structure, and the pointer is always the memory location of familyName in main().
That means every node will point to the same memory, and you're continuously updating that memory.
You won't notice the problem with the code as it stands, since you're only asking for one record. But it will become an issue when you start looping to get more records.
Your best bet is to use something like strdup() to make a copy of the string passed in, then each node will have its own memory location for strings:
p -> familyName = strdup (famName);
(don't forget to also free() the memory for each field once you're finished with it).
In the unlikely event your C implementation doesn't have a strdup(), see here.
There are several problems:-
It is not allowed to allocate memory when declaring a structure. Either, do the malloc inside your newNode() method Or, declare the structure like char familyName[50].
Result of malloc should not be casted.
It is better to use strcpy (or strdup) when copying 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.
main.h
#define DATA struct data
DATA
{
int id;
char data;
}
main.c
DATA *listOfData[100];
So at this point I will/should be able to access DATA in the list like this:
printf(listOfData[5]->data);
It isn't letting me do it, the run just freezes on that last print f...no error or anything.
This is because you have defined an array of pointers. But you never initialized any of the pointers.
Therefore:
printf(listOfData[5]->data);
will crash (undefined behavior) because you are dereferencing the (invalid) pointer at index 5.
*(And that's a very odd way to define a struct...)
To fix this issue, you will need to allocate for each of the pointers in the array. If you don't actually need it to be an array of pointers, then it might be better to just make it array of the struct itself:
DATA listOfData[100];
and access it as:
listOfData[5].data
Then you don't have to deal with allocating each element.
I'm not sure why printf would just freeze, but there's a couple of things wrong with this. First, all the pointers in your DATA* array are uninitialized. You probably intended to make an array of DATA, instead of an array of DATA pointers:
DATA listOfData[100];
You also didn't end the struct with a semicolon, so it seems unlikely that this would even compile:
#define DATA struct data
DATA
{
int id;
char data;
};
Finally, you're using printf in a rather unsafe way; the first argument needs to be a format string, or you can get weird behavior if the first argument has a % in it:
printf("%c\n", listOfData[5].data);
You haven't shown any memory allocation for the DATA *. Either declare your array as an array of struct data, like:
DATA listOfData[100];
or allocate memory dynamically and assign the pointers in your array.