Using pointers with functions and structs - c

Hello i'm selfstudying C and i'm a bit confused about the following code since i don't know if i'm understanding the code properly. I would be very thankful if someone could read my explanation and correct me if i'm wrong.
The code is from a header file. The function of the program should be uninteresting at this point, since my comprehension problem is about the pointers and the values the functions give back. So first of all i'm declaring 3 arrays of char and an integer in my employee struct.
struct employee
{
char firstname[11];
char lastname[11];
char number[11];
int salary;
}
5 functions are declared in the header file. The first function takes 4 values (3 pointers and one int) and gives back a pointer to a struct. The second function gets a pointer to the "struct employee" and gives back a pointer to an element of the array "char firstname" in the struct employee. The functions 3 and 4 are doing the same for the other both arrays. The function 5 gets a pointer to the struct employee but gives back an int and not a pointer. So it is just using the declared variable in the struct.
struct employee* createEmployee(char*, char*, char*, int); //1
char* firstname (struct Employee*); //2
char* lastname (struct Employee*); //3
char* number (struct Employee*); //4
int salary (struct Employee*); //5

Your understanding is pretty much correct. To be a little more accurate and/or less abusive of the English language, functions 2-4 return a pointer to an element of the corresponding array.
The idea is that the contents of each array represent some kind of text, with each element corresponding a character of text, up until the first appearance of a zero value (used to mark the end of the "string"). Keep in mind that there is no provision for Unicode here, or even for specifying an encoding: we assume ASCII, and for any bytes not in the range 0..127, all bets are off. A better name for the type char would be byte; but we didn't really know any better back then. (You should also be aware that char is a separate type from both signed char and unsigned char, and that char may or may not be signed.)
This way, the names and number can be any length up to ten (an 11th byte is reserved in order to have room for the "null terminator" with the zero value), and the returned pointer can be used to inspect - and modify; but that might not be a good idea - the data in the arrays that are part of the Employee structure.
The int returned as the Employee 's salary is a copy of the one in the struct. So although we can see the whole value, this does not let us modify the value in the struct. Of course, as long as we have the struct definition and an Employee instance, there is no protection; we can access the member directly instead of going through the function.
In C, we get "encapsulation" and "data hiding" by not providing these definitions. Instead, we would just put struct Employee; and the function declarations in the header, and the struct definition in the implementation file. Now calling code doesn't know anything about what an Employee is; only about what it can do.

Almost right, except when you read the functions, the input "char*" should be read as a string is passed in though technically it is a pointer. for integers the actual value is passed, so you are right there.
so,
struct employee* createEmployee(char*, char*, char*, int);
would mean that the procedure creates a employee with the four inputs passed (the first three are strings (Char*) which probably are first name, last name and number/id in that order and the last one is the salary.)

What you cannot be sure by just reading the function signature whether the values/pointers returned are reference to same values/pointers from the sturct, or the function(s) is creating a copy and returning pointer to the new value. This is why its a good idea to also write the documentation as comments with the function signature in the header file.

Your explanations make sense, except #2-4: since they return char*, they cannot return an element of a char array (the correct type for the latter would be simply char). Each of the three functions returns a pointer to char. One presumes that they return the pointer to the first element of the corresponding array, which is basically how arrays are passed around in C.

There is a problem in 1. What you're doing I assume is:
struct employee* createEmployee(const char* f, const char* l, const char* n,
const int sal)
{
struct employee* e;
strcpy(e->firstname, f);
strcpy(e->lastname, l);
/* ... */
return e;
}
The problem here is the arrays coming in. It is perfectly feasible for a char array of any size to be passed in; anything over the length of 11 would cause you to start overwriting data at &(e->firstname[0])+11;. Over what? Exactly. You've no idea (and nor have I, it'd be determined at run-time). This could cause some serious problems.
One way around that is to use functions from stdlib.h and string.h i.e. strlen() to test the length of the data being passed in to ensure it fits your field size.
A better method might be to write:
int createEmployee(struct employee* e, const char* f, const char* l, const char* n,
const int sal)
{
int error = 0;
if ( strlen(f) < 11 )
{
strncpy(e->firstname, f);
}
else
{
error++;
}
/* ... */
return error;
}
See what I've done? Yes it will work - anything passed in as a pointer can be modified. It's not pass-by-reference, quite. Edit: as aix says, pointers are "how arrays are passed around in C".
Another potential method is strncpy() which will truncate the source string according to the last argument, so strncpy(e->firstname, f, 11); would be safe.
You might well try dynamic memory allocation for the field sizes based on requirement, too. I'm guessing you'll be learning that later/as another challenge.
Also, another suggestion whilst we're at it is to define the pointer to a struct using typedef. It makes things a little more readable although the way you've done it is definitely clearer for someone learning.

Related

Why do C command line arguments include argc? [duplicate]

This is well known code to compute array length in C:
sizeof(array)/sizeof(type)
But I can't seem to find out the length of the array passed as an argument to a function:
#include <stdio.h>
int length(const char* array[]) {
return sizeof(array)/sizeof(char*);
}
int main() {
const char* friends[] = { "John", "Jack", "Jim" };
printf("%d %d", sizeof(friends)/sizeof(char*), length(friends)); // 3 1
}
I assume that array is copied by value to the function argument as constant pointer and reference to it should solve this, but this declaration is not valid:
int length(const char**& array);
I find passing the array length as second argument to be redundant information, but why is the standard declaration of main like this:
int main(int argc, char** argv);
Please explain if it is possible to find out the array length in function argument, and if so, why is there the redundancy in main.
sizeof only works to find the length of the array if you apply it to the original array.
int a[5]; //real array. NOT a pointer
sizeof(a); // :)
However, by the time the array decays into a pointer, sizeof will give the size of the pointer and not of the array.
int a[5];
int * p = a;
sizeof(p); // :(
As you have already smartly pointed out main receives the length of the array as an argument (argc). Yes, this is out of necessity and is not redundant. (Well, it is kind of reduntant since argv is conveniently terminated by a null pointer but I digress)
There is some reasoning as to why this would take place. How could we make things so that a C array also knows its length?
A first idea would be not having arrays decaying into pointers when they are passed to a function and continuing to keep the array length in the type system. The bad thing about this is that you would need to have a separate function for every possible array length and doing so is not a good idea. (Pascal did this and some people think this is one of the reasons it "lost" to C)
A second idea is storing the array length next to the array, just like any modern programming language does:
a -> [5];[0,0,0,0,0]
But then you are just creating an invisible struct behind the scenes and the C philosophy does not approve of this kind of overhead. That said, creating such a struct yourself is often a good idea for some sorts of problems:
struct {
size_t length;
int * elements;
}
Another thing you can think about is how strings in C are null terminated instead of storing a length (as in Pascal). To store a length without worrying about limits need a whopping four bytes, an unimaginably expensive amount (at least back then). One could wonder if arrays could be also null terminated like that but then how would you allow the array to store a null?
The array decays to a pointer when passed.
Section 6.4 of the C FAQ covers this very well and provides the K&R references etc.
That aside, imagine it were possible for the function to know the size of the memory allocated in a pointer. You could call the function two or more times, each time with different input arrays that were potentially different lengths; the length would therefore have to be passed in as a secret hidden variable somehow. And then consider if you passed in an offset into another array, or an array allocated on the heap (malloc and all being library functions - something the compiler links to, rather than sees and reasons about the body of).
Its getting difficult to imagine how this might work without some behind-the-scenes slice objects and such right?
Symbian did have a AllocSize() function that returned the size of an allocation with malloc(); this only worked for the literal pointer returned by the malloc, and you'd get gobbledygook or a crash if you asked it to know the size of an invalid pointer or a pointer offset from one.
You don't want to believe its not possible, but it genuinely isn't. The only way to know the length of something passed into a function is to track the length yourself and pass it in yourself as a separate explicit parameter.
As stated by #Will, the decay happens during the parameter passing. One way to get around it is to pass the number of elements. To add onto this, you may find the _countof() macro useful - it does the equivalent of what you've done ;)
First, a better usage to compute number of elements when the actual array declaration is in scope is:
sizeof array / sizeof array[0]
This way you don't repeat the type name, which of course could change in the declaration and make you end up with an incorrect length computation. This is a typical case of don't repeat yourself.
Second, as a minor point, please note that sizeof is not a function, so the expression above doesn't need any parenthesis around the argument to sizeof.
Third, C doesn't have references so your usage of & in a declaration won't work.
I agree that the proper C solution is to pass the length (using the size_t type) as a separate argument, and use sizeof at the place the call is being made if the argument is a "real" array.
Note that often you work with memory returned by e.g. malloc(), and in those cases you never have a "true" array to compute the size off of, so designing the function to use an element count is more flexible.
Regarding int main():
According to the Standard, argv points to a NULL-terminated array (of pointers to null-terminated strings). (5.1.2.2.1:1).
That is, argv = (char **){ argv[0], ..., argv[argc - 1], 0 };.
Hence, size calculation is performed by a function which is a trivial modification of strlen().
argc is only there to make argv length calculation O(1).
The count-until-NULL method will NOT work for generic array input. You will need to manually specify size as a second argument.
This is a old question, and the OP seems to mix C++ and C in his intends/examples. In C, when you pass a array to a function, it's decayed to pointer. So, there is no way to pass the array size except by using a second argument in your function that stores the array size:
void func(int A[])
// should be instead: void func(int * A, const size_t elemCountInA)
They are very few cases, where you don't need this, like when you're using multidimensional arrays:
void func(int A[3][whatever here]) // That's almost as if read "int* A[3]"
Using the array notation in a function signature is still useful, for the developer, as it might be an help to tell how many elements your functions expects. For example:
void vec_add(float out[3], float in0[3], float in1[3])
is easier to understand than this one (although, nothing prevent accessing the 4th element in the function in both functions):
void vec_add(float * out, float * in0, float * in1)
If you were to use C++, then you can actually capture the array size and get what you expect:
template <size_t N>
void vec_add(float (&out)[N], float (&in0)[N], float (&in1)[N])
{
for (size_t i = 0; i < N; i++)
out[i] = in0[i] + in1[i];
}
In that case, the compiler will ensure that you're not adding a 4D vector with a 2D vector (which is not possible in C without passing the dimension of each dimension as arguments of the function). There will be as many instance of the vec_add function as the number of dimensions used for your vectors.
int arsize(int st1[]) {
int i = 0;
for (i; !(st1[i] & (1 << 30)); i++);
return i;
}
This works for me :)
length of an array(type int) with sizeof:
sizeof(array)/sizeof(int)
Best example is here
thanks #define SIZE 10
void size(int arr[SIZE])
{
printf("size of array is:%d\n",sizeof(arr));
}
int main()
{
int arr[SIZE];
size(arr);
return 0;
}

C: get sizeof typedef struct array inside of function when passed as parameter [duplicate]

This is well known code to compute array length in C:
sizeof(array)/sizeof(type)
But I can't seem to find out the length of the array passed as an argument to a function:
#include <stdio.h>
int length(const char* array[]) {
return sizeof(array)/sizeof(char*);
}
int main() {
const char* friends[] = { "John", "Jack", "Jim" };
printf("%d %d", sizeof(friends)/sizeof(char*), length(friends)); // 3 1
}
I assume that array is copied by value to the function argument as constant pointer and reference to it should solve this, but this declaration is not valid:
int length(const char**& array);
I find passing the array length as second argument to be redundant information, but why is the standard declaration of main like this:
int main(int argc, char** argv);
Please explain if it is possible to find out the array length in function argument, and if so, why is there the redundancy in main.
sizeof only works to find the length of the array if you apply it to the original array.
int a[5]; //real array. NOT a pointer
sizeof(a); // :)
However, by the time the array decays into a pointer, sizeof will give the size of the pointer and not of the array.
int a[5];
int * p = a;
sizeof(p); // :(
As you have already smartly pointed out main receives the length of the array as an argument (argc). Yes, this is out of necessity and is not redundant. (Well, it is kind of reduntant since argv is conveniently terminated by a null pointer but I digress)
There is some reasoning as to why this would take place. How could we make things so that a C array also knows its length?
A first idea would be not having arrays decaying into pointers when they are passed to a function and continuing to keep the array length in the type system. The bad thing about this is that you would need to have a separate function for every possible array length and doing so is not a good idea. (Pascal did this and some people think this is one of the reasons it "lost" to C)
A second idea is storing the array length next to the array, just like any modern programming language does:
a -> [5];[0,0,0,0,0]
But then you are just creating an invisible struct behind the scenes and the C philosophy does not approve of this kind of overhead. That said, creating such a struct yourself is often a good idea for some sorts of problems:
struct {
size_t length;
int * elements;
}
Another thing you can think about is how strings in C are null terminated instead of storing a length (as in Pascal). To store a length without worrying about limits need a whopping four bytes, an unimaginably expensive amount (at least back then). One could wonder if arrays could be also null terminated like that but then how would you allow the array to store a null?
The array decays to a pointer when passed.
Section 6.4 of the C FAQ covers this very well and provides the K&R references etc.
That aside, imagine it were possible for the function to know the size of the memory allocated in a pointer. You could call the function two or more times, each time with different input arrays that were potentially different lengths; the length would therefore have to be passed in as a secret hidden variable somehow. And then consider if you passed in an offset into another array, or an array allocated on the heap (malloc and all being library functions - something the compiler links to, rather than sees and reasons about the body of).
Its getting difficult to imagine how this might work without some behind-the-scenes slice objects and such right?
Symbian did have a AllocSize() function that returned the size of an allocation with malloc(); this only worked for the literal pointer returned by the malloc, and you'd get gobbledygook or a crash if you asked it to know the size of an invalid pointer or a pointer offset from one.
You don't want to believe its not possible, but it genuinely isn't. The only way to know the length of something passed into a function is to track the length yourself and pass it in yourself as a separate explicit parameter.
As stated by #Will, the decay happens during the parameter passing. One way to get around it is to pass the number of elements. To add onto this, you may find the _countof() macro useful - it does the equivalent of what you've done ;)
First, a better usage to compute number of elements when the actual array declaration is in scope is:
sizeof array / sizeof array[0]
This way you don't repeat the type name, which of course could change in the declaration and make you end up with an incorrect length computation. This is a typical case of don't repeat yourself.
Second, as a minor point, please note that sizeof is not a function, so the expression above doesn't need any parenthesis around the argument to sizeof.
Third, C doesn't have references so your usage of & in a declaration won't work.
I agree that the proper C solution is to pass the length (using the size_t type) as a separate argument, and use sizeof at the place the call is being made if the argument is a "real" array.
Note that often you work with memory returned by e.g. malloc(), and in those cases you never have a "true" array to compute the size off of, so designing the function to use an element count is more flexible.
Regarding int main():
According to the Standard, argv points to a NULL-terminated array (of pointers to null-terminated strings). (5.1.2.2.1:1).
That is, argv = (char **){ argv[0], ..., argv[argc - 1], 0 };.
Hence, size calculation is performed by a function which is a trivial modification of strlen().
argc is only there to make argv length calculation O(1).
The count-until-NULL method will NOT work for generic array input. You will need to manually specify size as a second argument.
This is a old question, and the OP seems to mix C++ and C in his intends/examples. In C, when you pass a array to a function, it's decayed to pointer. So, there is no way to pass the array size except by using a second argument in your function that stores the array size:
void func(int A[])
// should be instead: void func(int * A, const size_t elemCountInA)
They are very few cases, where you don't need this, like when you're using multidimensional arrays:
void func(int A[3][whatever here]) // That's almost as if read "int* A[3]"
Using the array notation in a function signature is still useful, for the developer, as it might be an help to tell how many elements your functions expects. For example:
void vec_add(float out[3], float in0[3], float in1[3])
is easier to understand than this one (although, nothing prevent accessing the 4th element in the function in both functions):
void vec_add(float * out, float * in0, float * in1)
If you were to use C++, then you can actually capture the array size and get what you expect:
template <size_t N>
void vec_add(float (&out)[N], float (&in0)[N], float (&in1)[N])
{
for (size_t i = 0; i < N; i++)
out[i] = in0[i] + in1[i];
}
In that case, the compiler will ensure that you're not adding a 4D vector with a 2D vector (which is not possible in C without passing the dimension of each dimension as arguments of the function). There will be as many instance of the vec_add function as the number of dimensions used for your vectors.
int arsize(int st1[]) {
int i = 0;
for (i; !(st1[i] & (1 << 30)); i++);
return i;
}
This works for me :)
length of an array(type int) with sizeof:
sizeof(array)/sizeof(int)
Best example is here
thanks #define SIZE 10
void size(int arr[SIZE])
{
printf("size of array is:%d\n",sizeof(arr));
}
int main()
{
int arr[SIZE];
size(arr);
return 0;
}

Re: Struct Array with Varying Size Structs--Clarification

I have a question regarding one of the solutions that was posted--the accepted one on this thread:
https://stackoverflow.com/a/4982586/5854333 .
I would have left a comment on it instead of starting a new question thread, but I do not currently have the experience necessary. The program indeed runs as promised and is similar to what I intend to actually implement, but I'm still confused as to whether there may be subtle memory issues in it.
For example, in the portion:
void addStringToHolder(stringHolder * holder, const char * string) {
char ** newStrings = realloc(holder->strings, newStringCount * sizeof(char *));
if (newStrings != NULL) {
holder->strings = newStrings;
}
}
(we are working in this function with the struct)
typedef struct {
int numberOfStrings;
char ** strings;
}stringHolder;
Can the double pointer strings really be modified in this function? I thought we always had to pass in a pointer to the thing we wanted to modify, rather than the thing itself. Wouldn't we have to pass in a triple pointer if we wanted to modify the double pointer?
Of course we are also passing in a pointer to the struct in the first place, so does that make this work? I think I'm getting lost in all of these pointers. A little clarity would be helpful. Hopefully understanding this case will allow me to understand the others.
Can the double pointer strings really be modified in this function?
Shortly, yes.
To elaborate:
A pointer in C is just a location in the memory, when you pass it to a function you simply tell the function where to preform its operation.
By passing in a pointer to the struct, we are calling all of its elements by reference, and thus we can modify any of its elements, including the double pointer strings.
Say we have a pointer to your struct stringHolder* h_ptr where:
typedef struct {
int numberOfStrings;
char ** strings;
}stringHolder;
Now using * to dereference the pointer(s) you can access every level:
h_ptr /*some adress in memory*/
*h_ptr /*the value stored in said adress (we know its a stringHolder)*/
using the syntax x->y instead of (*x).y for readability
h_ptr->numberOfStrings /*the integer value stored in this struct*/
h_ptr->strings /*a pointer to an array of C string pointers*/
*(h_ptr->strings) /*the first "string" in said array, same as saying
a pointer to the first char in the first "string"*/
**(h_ptr->strings) /*the first char of the first "string"*/
And with pointer arithmetic we can get wherever we want and modify the values (as long as we keep the C convention of null terminated strings)
*(h_ptr->strings + 1) /*the second "string" in strings array*/
*(*(h_ptr->strings + 2) + 4) /*the fifth char in the third "string"*/
and so on.

function with a struct array pointer as an argument, C language

typedef struct {
char manufacturer[SIZE];
char model[SIZE];
int size;
int id;
int qty;
double cost;
double price;
} tv;
void firstSix(tv *tvarr[]);
void firstSix(tv *tvarr[])
{
(*tvarr[0]).manufacturer = "Vizio";
}
I am making an inventory program. It consists of an array of structs that will store information about different televisions. In my program I am required to hardcode six entries into the array, so I am trying to make a function that will take a struct array pointer argument. In the above code, I included the struct declaration, the function prototype and function definition that I am trying to make. Everything is placed before and after main in the respective order. I don't understand why Visual Studio is highlighting the first parenthesis in the code inside the function definition and saying "expression must be a modifiable lvalue". I don't understand what it is that I am doing wrong. Please help.
You cannot assign an array like that. You need to do
strcpy ((*tvarr[0]).manufacturer, "Vizio");
Make sure that you don't go out of bounds when copying the string into the array.
You can either check the size of the string in advance or use strncpy which will limit the maximum number of characters to be copied.
An array is not a modifiable l-value. So basically you cannot have it on the left hand side of an assignment.
Or may be you also might want to define manufacture as char *manufacture and then dynamically allocate the string.
manufacturer = strdup ("Vizio"); //manufacturer is char *
Or depending on the length first allocate the buffer
manufacturer = malloc (sizeof (char) * needed_bytes);
Whenever you dynamically allocate the buffer, whenever you have finished working with it always remember to free it free (manufacturer).
I think you want to do something like
strncpy((tvarr[0])->manufacturer, "Vizio", SIZE - 1);
Kevin has it; you can't assign a string to a pointer, you must copy the data to the array. I suggest strncpy to keep from running off the end of the allocated space.

Copying one structure to another

I know that I can copy the structure member by member, instead of that can I do a memcpy on structures?
Is it advisable to do so?
In my structure, I have a string also as member which I have to copy to another structure having the same member. How do I do that?
Copying by plain assignment is best, since it's shorter, easier to read, and has a higher level of abstraction. Instead of saying (to the human reader of the code) "copy these bits from here to there", and requiring the reader to think about the size argument to the copy, you're just doing a plain assignment ("copy this value from here to here"). There can be no hesitation about whether or not the size is correct.
Also, if the structure is heavily padded, assignment might make the compiler emit something more efficient, since it doesn't have to copy the padding (and it knows where it is), but mempcy() doesn't so it will always copy the exact number of bytes you tell it to copy.
If your string is an actual array, i.e.:
struct {
char string[32];
size_t len;
} a, b;
strcpy(a.string, "hello");
a.len = strlen(a.string);
Then you can still use plain assignment:
b = a;
To get a complete copy. For variable-length data modelled like this though, this is not the most efficient way to do the copy since the entire array will always be copied.
Beware though, that copying structs that contain pointers to heap-allocated memory can be a bit dangerous, since by doing so you're aliasing the pointer, and typically making it ambiguous who owns the pointer after the copying operation.
For these situations a "deep copy" is really the only choice, and that needs to go in a function.
Since C90, you can simply use:
dest_struct = source_struct;
as long as the string is memorized inside an array:
struct xxx {
char theString[100];
};
Otherwise, if it's a pointer, you'll need to copy it by hand.
struct xxx {
char* theString;
};
dest_struct = source_struct;
dest_struct.theString = malloc(strlen(source_struct.theString) + 1);
strcpy(dest_struct.theString, source_struct.theString);
If the structures are of compatible types, yes, you can, with something like:
memcpy (dest_struct, source_struct, sizeof (*dest_struct));
The only thing you need to be aware of is that this is a shallow copy. In other words, if you have a char * pointing to a specific string, both structures will point to the same string.
And changing the contents of one of those string fields (the data that the char * points to, not the char * itself) will change the other as well.
If you want a easy copy without having to manually do each field but with the added bonus of non-shallow string copies, use strdup:
memcpy (dest_struct, source_struct, sizeof (*dest_struct));
dest_struct->strptr = strdup (source_struct->strptr);
This will copy the entire contents of the structure, then deep-copy the string, effectively giving a separate string to each structure.
And, if your C implementation doesn't have a strdup (it's not part of the ISO standard), get one from here.
You can memcpy structs, or you can just assign them like any other value.
struct {int a, b;} c, d;
c.a = c.b = 10;
d = c;
In C, memcpy is only foolishly risky. As long as you get all three parameters exactly right, none of the struct members are pointers (or, you explicitly intend to do a shallow copy) and there aren't large alignment gaps in the struct that memcpy is going to waste time looping through (or performance never matters), then by all means, memcpy. You gain nothing except code that is harder to read, fragile to future changes and has to be hand-verified in code reviews (because the compiler can't), but hey yeah sure why not.
In C++, we advance to the ludicrously risky. You may have members of types which are not safely memcpyable, like std::string, which will cause your receiving struct to become a dangerous weapon, randomly corrupting memory whenever used. You may get surprises involving virtual functions when emulating slice-copies. The optimizer, which can do wondrous things for you because it has a guarantee of full type knowledge when it compiles =, can do nothing for your memcpy call.
In C++ there's a rule of thumb - if you see memcpy or memset, something's wrong. There are rare cases when this is not true, but they do not involve structs. You use memcpy when, and only when, you have reason to blindly copy bytes.
Assignment on the other hand is simple to read, checks correctness at compile time and then intelligently moves values at runtime. There is no downside.
You can use the following solution to accomplish your goal:
struct student
{
char name[20];
char country[20];
};
void main()
{
struct student S={"Wolverine","America"};
struct student X;
X=S;
printf("%s%s",X.name,X.country);
}
You can use a struct to read write into a file.
You do not need to cast it as a `char*.
Struct size will also be preserved.
(This point is not closest to the topic but guess it:
behaving on hard memory is often similar to RAM one.)
To move (to & from) a single string field you must use strncpy
and a transient string buffer '\0' terminating.
Somewhere you must remember the length of the record string field.
To move other fields you can use the dot notation, ex.:
NodeB->one=intvar;
floatvar2=(NodeA->insidebisnode_subvar).myfl;
struct mynode {
int one;
int two;
char txt3[3];
struct{char txt2[6];}txt2fi;
struct insidenode{
char txt[8];
long int myl;
void * mypointer;
size_t myst;
long long myll;
} insidenode_subvar;
struct insidebisnode{
float myfl;
} insidebisnode_subvar;
} mynode_subvar;
typedef struct mynode* Node;
...(main)
Node NodeA=malloc...
Node NodeB=malloc...
You can embed each string into a structs that fit it,
to evade point-2 and behave like Cobol:
NodeB->txt2fi=NodeA->txt2fi
...but you will still need of a transient string
plus one strncpy as mentioned at point-2 for scanf, printf
otherwise an operator longer input (shorter),
would have not be truncated (by spaces padded).
(NodeB->insidenode_subvar).mypointer=(NodeA->insidenode_subvar).mypointer
will create a pointer alias.
NodeB.txt3=NodeA.txt3
causes the compiler to reject:
error: incompatible types when assigning to type ‘char[3]’ from type ‘char *’
point-4 works only because NodeB->txt2fi & NodeA->txt2fi belong to the same typedef !!
A correct and simple answer to this topic I found at
In C, why can't I assign a string to a char array after it's declared?
"Arrays (also of chars) are second-class citizens in C"!!!

Resources