So this is my code and I don't understand why I get that identifier "pers" is undefined, when I'm clearly pointing at it from another function, which is as far as I know, the utility of pointers.
I've gone through some research but nothing seemed to solve my issue since I'm dealing with structs and all that.
Also one of the requirements is that tle so called "leer_persona();" cant have any value in the parenthesis
#include <stdio.h>
typedef struct{
int num;
char letra;
}tdni;
typedef struct{
char nom[20];
tdni dni;
}tpersona;
tpersona leer_persona();
void mostrar_persona(tpersona p);
int main(){
tpersona pers;
pers = leer_persona();
mostrar_persona(pers);
return 0;
}
tpersona leer_persona(){
int i=0;
int *fp;
fp = &pers;
Thanks.
Pers has function scope in "main()". It is not visible outside of "main()".
https://www.geeksforgeeks.org/scope-rules-in-c/
Function scope begins at the opening of the function and ends with the
closing of it.
See this link for more details: C - Scope Rules
If you want to use "pers" in another function, you'd typically pass it as a function parameter, e.g. tpersona leer_persona(tpersona * pers). In this example, I passed parameter "pers" by reference, instead of copying by value.
Related
I want to return the name of the smallest city population-wise, if it is the second city. (Please don't mind the if statement, I know it's bland), the missing return is what bothers me.
I assume I should declare a pointer inside the function rSmallestCity, like *rtrn but I guess the source variable is destroyed before it is used?
typedef struct Coordinate{
int x,y;
}Coordinate;
typedef struct city{
char name[20];
int population;
Coordinate coordinates;
}city;
char *rSmallestCity(city **cl, int n)
{
char *rtrn = NULL;
if(cl[n-2]->population>cl[n-1]->population)
{
rtrn = &cl[n-1]->name;
}
return rtrn;
}
int main()
{
city c1 ={.name="Mumbai", .population=310, .coordinates.x=3, .coordinates.y=4};
city c2 ={.name="Delhi", .population=300, .coordinates.x=3, .coordinates.y=2};
city *clist[2];
clist[0]=&c1;
clist[1]=&c2;
printf("\n%s is smallest\n",rSmallestCity(clist,2));
}
warning: assignment to 'char ' from incompatible pointer type 'char ()[20]' [-Wincompatible-pointer-types]|
I assume I should declare a pointer inside the function rSmallestCity, like *rtrn but I guess the source variable is destroyed before it is used?
A good question. And your assumption is correct. Creating a variable inside a function it's existence ends upon leaving the function. But in this case, because the struct member name is already a char * you do not need to create another variable. Just return c1.name. (see code example below.)
A few other suggestions:
In the struct declaration:
typedef struct Coordinate{
int x,y;
}Coordinate;
You've used the same symbol (Coordinate) for the struct name, and for it's typedef. This is not a good practice. If you need both a struct name and a typedef, pick different symbols. BTW, in this this example, only one or the other is needed. Say you pick the typedef, then the struct is completely defined by:
typedef struct {
int x,y;
}Coordinate;
That suggestion applies to both struct declarations in your example code.
The signatures for the main function do not include int main(){...} rather
int main(void){..., return 0;} and int main(int argc, char *argv[]){..., return 0;}
The following code example illustrates some of the other suggestions for improvements in comments under your post,
typedef struct {
int x,y;
}Coordinate;
typedef struct {
char name[20];
int population;
Coordinate coordinates;
}city;
//return char * rather than char to allow for full null terminated char array (string)
char * rSmallestCity(city c1[],int cityCount)//generisize function prototype to
{ //to easily accommodate bigger arrays if needed
long long size, sizeKeep = 8e9; //index and population. initialize larger than possible population
int indexKeep = 0;
//note you do not need to define a char *, the struct already contains one
for(int i=0; i<cityCount; i++)//use a loop rather than a single comparison, keep the smalles
{
size = c1[i].population;
sizeKeep = (size < sizeKeep) ? indexKeep = i, size : sizeKeep;
}
printf("\n%s\n",c1[indexKeep].name);
return c1[indexKeep].name;
};
int main(void)//use minimum signature for main, and call return before leaving.
{
//combining your original declarations and assignments for struct
//into a single declaration/definition.
city c1[] = {{.name="Mumbai", .population=310, .coordinates.x=3, .coordinates.y=4},
{.name="Delhi", .population=300, .coordinates.x=3, .coordinates.y=2}};
int cityCount = sizeof(c1)/sizeof(c1[0]);
printf("\n%s is smallest",rSmallestCity(c1, cityCount));
return 0;
};
The solution that I originally left in comment under OP (remove & in the line &cl[n-1]->name;) needs some explanations to avoid problems later.
(It is an educational answer not a full answer on pointers, array decay, ... And many examples can be found on stackoverflow. I tried to simplify)
Try this simple code.
int main()
{
char myString1[25]="Toulouse" ; // French City
printf("%p\n",myString1);
printf("%p\n",&myString1);
}
The output is the same, but an array name and the address of an array name are not the same. The array name is evaluated to the address of its first element. So it works in your case but a warning is issued during compilation and it is very important. Firstly, do not remove compilation warnings.
Now, try this code :
int main()
{
char myString1[25]="Toulouse" ; // French City
printf("%p\n",myString1+1);
printf("%p\n",&myString1+1);
}
The outputs are different. Because myString1 is evaluated to char* and &myString1 to char [25]. So +1, in the first, case adds one (sizeof char) to the pointer and in the other case, it adds 25.
Delete the "&" in the line:
rtrn = &cl[n-1]->name;
To extremely simplify, you assigned an "address of char[]" to a char*, but array syntax makes it work regardless.
As shown in this small script.
#include <stdio.h>
struct student{
short count;
void (*addCount)();
};
void student_addCount(struct student a){
a.count++;
}
int main(){
struct student student;
student.addCount = student_addCount;
student.count = 0;
student.addCount();
student.addCount();
student.addCount();
student.addCount();
student.addCount();
printf("%d\n",student.count);
}
I have added a pointer to a function inside a struct, but I do not know why this works as the function 'addCount' is not receiving any arguments and it actually adds up the number of times specified.
I am compiling this code with GCC 6.3.0 in different environments such as ideone.com, wandbox.org and the compiler in WSL.
here is the proof that it works with ideone.
https://ideone.com/Cam4xY
That's not a function inside a structure, it's a function pointer inside a structure.
void (*addCount)();
defines addCount as a pointer to a function. The function returns void and takes an unspecified number of arguments.
That's what the empty parentheses mean. That's an old-style non-prototype function declaration. There is rarely, if ever, a good reason to use non-prototype function declarations or definitions. If you want to specify tht a function takes no arguments, use (void) rather than ().
student.addCount = student_addCount;
The function student_addCount takes a struct student argument, but its type is still compatible with the type of your pointer member. Assigning it like this essentially disables checking on calls. This is why old-style function declarations are a bad idea.
student.addCount();
This is an indirect call via the function pointer. Since the function pointer type doesn't specify how many arguments are expected, the call is legal. Since the actual function being called requires a single argument of type struct student, the behavior is undefined. With old-style function declarations, it's entirely up to you, the programmer, to get the arguments right; the compiler won't help you.
Since you're getting what appear to be valid results, it's likely that the argument you expected to be passed happened to be in the right place in memory, perhaps on top of the stack. The function is called and it assumes, quite reasonably, that you've passed a proper argument value. It looks for that argument in memory, or in a register, and finds ... something.
Here's a version of your program without the undefined behavior:
#include <stdio.h>
struct student{
short count;
void (*addCount)(struct student a);
};
void student_addCount(struct student a){
a.count++;
}
int main(void){
struct student student;
student.addCount = student_addCount;
student.count = 0;
student.addCount(student);
student.addCount(student);
student.addCount(student);
student.addCount(student);
student.addCount(student);
printf("%d\n",student.count);
}
The output is 0 -- because the count being incremented is a member of the parameter, which is a local object.
Here's a version that does what you probably want. It passes a pointer to the structure, so the count member of your original struct student object is incremented by the function. The output is 5.
#include <stdio.h>
struct student{
short count;
void (*addCount)(struct student *a);
};
void student_addCount(struct student *a){
a->count++;
}
int main(void){
struct student student;
student.addCount = student_addCount;
student.count = 0;
student.addCount(&student);
student.addCount(&student);
student.addCount(&student);
student.addCount(&student);
student.addCount(&student);
printf("%d\n",student.count);
}
I came across this code.
typedef __mpz_struct MP_INT;
typedef __mpz_struct mpz_t[1];
Here the struct __mpz_struct is a struct that is typedefed to an array of single element. I understand that this is a trick to pass by reference in C. Then mpz_t has been used as a type to declare variables and pass them to function as parameters. Also, There was one more comment
/*
MP_INT*, MP_RAT* and MP_FLOAT* are used because they don't have side-effects
of single-element arrays mp*_t
*/
What kind of side effects are they talking about?
Passing an array to a function let's the array decay to a pointer to it's 1st element.
One can achieve the same effect by applying the Address-Of operator & to a simple variable of the same type as the array's elements.
Examples:
struct S
{
int i;
float f;
};
This
void set_S(struct S * ps)
{
ps->i = 40;
ps->f = 2.;
}
is equivalent to
void set_S(struct S ps[1])
{
ps->i = 40;
ps->f = 2.;
}
is equivalent to
void set_S(struct S * ps)
{
ps[0].i = 40;
ps[0].f = 2.;
}
is equivalent to
void set_S(struct S ps[1])
{
ps[0].i = 40;
ps[0].f = 2.;
}
One-Element-Array approach:
typedef struct S Array_of_S_with_size_1[1];
int main(void)
{
Array_of_S_with_size_1 array_of_S_with_size_1;
array_of_S_with_size_1[0].i = 0;
array_of_S_with_size_1[0].f = 0.;
set_S(array_of_S_with_size_1);
...
}
The above main() provides the same functionality as the following:
int main(void)
{
struct S s;
s.i = 0;
s.f = 0.;
set_S(&s);
...
}
I do not see any gain using the "One-Element-Array" approach. An expection might be if the &-key is broken on ones keyboard ... ;-)
I see two parts to your question. The first part, how the typedef works for passing arguments to functions, would better be illustrated with an example. Without it, I'll have to guess a bit.
In C function declarations, an array parameter is equivalent to a pointer. That's why you see (for example) equivalently for the main function,
int main(int argc, char **argv)
and
int main(int argc, char *argv[])
Similarly, if a function in your program would be declared
int func(__mpz_struct *arg)
it would be equivalent to
int func(__mpz_struct arg[])
and hence to
int func(mpz_t arg)
Also, on the calling side, if you have a variable of type mpz_t, hence the array, and you pass it to a function, the "pointer decay" takes effect: in an expression, if you use (the name of) an array it "decays" into a pointer to its first element.
This way you can call the function:
mpz_t value;
func(value);
Of course, to modify these mpz_t objects outside of the API functions, you still have to be aware of their true nature.
The side effects that you mention, I would also have to guess about them. Possibly it is meant that you have to be aware you're working with pointers inside the functions. It might be considered better to make that explicit by using the pointer syntax.
You can assign an MP_INT to another but you can not assign an mpz_t to another since assignment is not defined for arrays. If you do not want your clients to assign variables other than by your methods (which might do memory managements and stuff) this is the trick for you.
Look at this sample code
typedef char type24[3];
Same as your, but well known data type 'char' insted of your struct __mpz_struct type.
above type def means, I am using above typedef to represent char[3].
So in your sample code,
typedef __mpz_struct mpz_t[1];
mpz_t should be __mpz_struct type.
I'm tasked with adding the quick-fit allocation algorithm to MINIX, and as such need to use structures a lot. However, I came accross something for which I cannot find any resources on a solution.
The below code is a quick example I made to demonstrate the issue I have met with.
#include <stdlib.h>
#include <stdio.h>
struct some_struct {
int h_count;
};
void why();
struct some_struct * myStruct;
int main(){
myStruct = (struct some_struct *) malloc(sizeof(struct some_struct));
myStruct->h_count=0;
printf("%d\n", myStruct->h_count);
why(&myStruct);
return 0;
}
void why(struct some_struct * t_some_struct){
printf("%d\n", t_some_struct->h_count);
}
The output of the printf in the function why is different from the output given in main. The value printed by why is a seemingly random number that changes every time the program is ran.
Output:
0
7870280
Press any key to continue . . .`
The 7870280 changes on every run. I would assume it is printing some kind of memory value or something, but that's just a guess as I have no idea really.
As such, I thought I'd ask here for the benefit of others alongside myself:
Why does this occur?
Is my syntax the issue here?
How do I use a pointer to a structure as a parameter for some function, then reference the given structure's members in the scope of the function? (I'd like to use h_count for t_some_struct as 0)
Thanks
The function why expects a pointer whereas you are passing a pointer to pointer. Call as
why(myStruct); (by the way, myStruct is a global variable, so passing is a bit superfluous here). Rest of your accessing the struct member is fine.
Not directly related but some general suggestions:
1) Use standard prototype for main() such as int main(int argc, char*argv[])
2) Casting the result of malloc is needless and error-prone.
I am making a reliable data transfer protocol and have the function prototype
void tolayer5(int, char data[]);
With the structs
struct msg {
char data[20];
};
struct pkt {
int seqnum;
int acknum;
int checksum;
char payload[20];
};
And when I call the function in this format:
tolayer5(A, packet.payload);
Where A is an int and packet.payload is a struct pkt, I get the error "undefined reference to 'tolayer5(int, char*)'. Can you help me see what I'm missing here?
void tolayer5(int AorB, char data[])
{
int i;
if (TRACE>2)
{
printf("TOLAYER5: data received:");
for (i=0; i<20; i++)
printf("%c",data[i]);
printf("\n");
}
}
Thank you all for helping with the original issue! :) When trying to fix that one, however, I ran into an infinite loop that I think has something to do with me addressing characters in an array incorrectly (it's been awhile since I've done C like this. Can you help me to find where I'm creating an infinite loop?
I have updated the above code to what I'm now working with. Notice the main changes have been to my function:
void tolayer5(int AorB, char data[])
And this line inside the function: printf("%c",msgReceived.data[i]); since now it's just:
printf("%c",data[i]);
seems you need to link with the obj file that implements tolayer5()
Update:
your function declaration doesn't match the implementation:
void tolayer5(int AorB, struct msg msgReceived)
void tolayer5(int, char data[])
So compiler would treat them as two different functions (you are using c++). and it cannot find the implementation for the one you called in main().
Make sure your declare the tolayer5 function as a prototype, or define the full function definition, earlier in the file where you use it.
As stated by a few others, this is a linking error. The section of code where this function is being called doesn't know what this function is. It either needs to be declared in a header file an defined in its own source file, or defined or declared in the same source file, above where it's being called.
Edit: In older versions of C, C89/C90, function declarations weren't actually required. So, you could just add the definition anywhere in the file in which you're using the function, even after the call and the compiler would infer the declaration. For example,
int main()
{
int a = func();
}
int func()
{
return 1;
}
However, this isn't good practice today and most languages, C++ for example, won't allow it. One way to get away with defining the function in the same source file in which you're using it, is to declare it at the beginning of the file. So, the previous example would look like this instead.
int func();
int main()
{
int a = func();
}
int func()
{
return 1;
}