how to use pointers in structures? - c

I used pointer while printing structure elements but its working without using pointer in the print statement but shouldn't we use pointers to gather the element from the variable address why is it different in the structure case and its different in string also . Can anyone tell me why is that ?
#include <stdio.h>
int main(){
struct books{
char name[10];
int page;
};
struct books b1={"book1",1};
struct books *ptr;
ptr=&b1;
printf("%s %d",ptr->name,ptr->page);
}

printf("%s %d",*ptr->name,*ptr->page);
is wrong. A->B means (*A).B. You should do either
printf("%s %d",ptr->name,ptr->page);
or
printf("%s %d",(*ptr).name,(*ptr).page);

What MikeCAT said.
Beware though that an array would also be a pointer so *ptr->name would compile but will produce the first character of 'name'.
struct books{
char name[10];
int page;
};
ptr=&b1;
printf("%c",*ptr->name);

Pointers used when the object is too big and copying such object vastes time. But in your struct it takes 10 bytes for char array + 4 bytes for int and it's not a problem. In 64 bit machine pointers take 8 bytes in 32 bit 4 bytes. Suppose you have a big a struct and per object it takes 50 bytes of memory if you copy it will take more space and will be slower and by copying a brand new object will be created and that won't change anything in original one.
Let's see in practice when pointers can be used:
#include <stdio.h>
struct person{
char name[10];
int age;
};
void grow(struct person p) {
++p.age;
}
int main(){
struct person Mike = { "Mike", 20 };
grow(Mike);
printf("Name: %s\tAge: %d", Mike.name, Mike.age);
}
OUTPUT:
Name: Mike Age: 20
This code won't change age of Mike because void grow(struct person p) function copies struct person by creating a new object then increments age and at the end destroys struct person p. If you pass it as pointer then Mike will be modified.

Related

calloc sometimes gives double the amount of memory asked

I came across something I don't understand why and I'd like to hear an explanation about it.
I have this struct:
typedef struct Student {
int age;
char *name;
} Student;
int main()
{
Student **test1 = calloc(2, sizeof(*test1));
Student **test2 = calloc(2, sizeof(**test2));
return 0;
}
I've noticed that test1 gets 2 memory allocations (as it should) while test2 gets 4. Why is that and which is the correct usage? I assume its the first one but i'm not sure why.
Thanks!
sizeof(*test1) is the size of a pointer Student*, while sizeof(**test) is the size of a structure Student.The structure has a pointer, so its size should be larger than the size of a pointer.
Student **test1 = calloc(2, sizeof(*test1));
Is the typical usage. This is allocating 2-element array of Student* and assigning the pointer to its first element to test1.
Two things here:
You're allocating two different amounts of memory here. In the first case, you allocate space for 2 objects of type Student *, while in the second case you allocate space for 2 objects of type Student. The latter is likely larger than the former, so you'll be able to put more object of type Student * there.
You don't show how you're verifying how much memory you've gotten, but it's undefined behavior to read or write past the bounds of allocated memory. Your program might crash, or it might not.
sizeof(*test) is a size in bytes of the pointer to Student. It will be on most systems 4 or 8.
sizeof(**test)gives you the size of the Student. The allocation (test2) makes no sense at all.
You can easily test it yourself by printing the sizes:
#include <stdio.h>
#include <malloc.h>
typedef struct Student {
int age;
char *name;
double somedata[100];
} Student;
int main()
{
Student **test1;
Student **test2;
printf("%zu\n", sizeof(*test1));
printf("%zu\n", sizeof(**test2));
return 0;
}
https://godbolt.org/z/W6e8YzKKf

What happens when dereferencing a pointer to a struct in C?

Say I'm using 2 structs in C like:
struct department {
char name[10];
int floor;
}
struct person {
char name[10];
struct department *dep;
};
What happens under the hood, when accessing a variable person_1 of type person like this:
(person_1.dep)->floor.
First, the dep pointer is dereferenced, but after, are the first 10 of the name of the department simply skipped over to get the 4 bytes of the floor, or is there more to it?
Thanks!

display a specified index of a pointer char*

I am trying to point on a specified character in a string contained on a structure
here my code
typedef struct{
char *name;
int age;
}PERSON, *person;
int main(){
person serenity;
serenity = (person)malloc(sizeof(PERSON));
strcpy(&(serenity->name),"Serenity");
printf("%c",*(&(serenity->name)+1));
}
here i wanted to display the second character which is 'e' but it shows 'n' instead
anyone can explain me what is wrong with this,
thank you
You have not allocated memory for name
typedef struct{
char *name;
int age;
}PERSON, *person;
int main(){
person serenity;
serenity = malloc(sizeof(PERSON));
serenity->name = malloc(sizeof("Serenity")); //<< Missing
strcpy((serenity->name),"Serenity");
printf("%c",*((serenity->name)+1)); // << Also you want the value in pointer name NOT its address
return 0;
}
Outputs e. Also since you tagged C there is no need to cast the return type of malloc.
Okay, okay... All of those answers aside, if you do not aim to change the characters inside the string "Serenity" in the future, you could just do the following:
#include <stdio.h>
typedef struct{
const char *name; // <-- added const
int age;
}PERSON, *person;
int main( ){
person serenity;
serenity = (person) malloc( sizeof( PERSON ) );
serenity->name = "Serenity"; // <-- simply assigned the pointer with the
// address to the array of constant characters
printf( "%c", *( serenity->name + 1 ) ); // <-- changed this
}
This statement
serenity = (person)malloc(sizeof(PERSON));
allocates the structure
typedef struct{
char *name;
int age;
}PERSON
however name is kept uninitialized and points somewhere in memory causing a crash when you copy to it.
So instead of
strcpy(&(serenity->name),"Serenity");
write
serenity->name = strdup("Serenity");
which is the same as
serenity->name = malloc(strlen("Serenity")+1);
strcpy(serenity->name,"Serenity");
don't forget to free that string as well later.
Try printf("%c",*(serenity->name+1));, also do strcpy(serenity->name,"Serenity");.
If you have a pointer char* name; you access the second element by doing name[1] or *(name+1). &name will give you the address where the pointer address of name is stored. This is not what you want here.
Another issue in your program is that you never allocate memory for the variable name. You need a serenity->name = (char*)malloc(128);. But using an arbitrary length like 128 is very dangerous in combination with strcpy. Use strncpy instead of strcpy to work around this.

Sub-scripted value is neither array nor pointer

So I am trying to make a simple program which opens up a text file, reads the number of students that the file contains, their first names, last names and student numbers, and stores values in variables, and then finally returns a pointer to an array of those student objects. My code is as follows: -
#include <stdio.h>
#include <stdlib.h>
struct student
{
double studentNumber;
char *firstName;
char *lastName;
};
struct student *readStudentRecordFile(char *fileName, int *numOfStudents)
{
int i;
struct student a;
FILE *fp;
fp=fopen(fileName,"r");
fscanf(fp,"%d",&numOfStudents);
for(i=0;i<*numOfStudents;i++)
{
fscanf(fp, "%s" "%s" "%f", a[i].firstName,a[i].lastName,&a[i].studentNumber);
}
fclose(fp);
}
int main(void)
{
int nStudents;
struct student *readArray;
readArray=readStudentRecordFile("hello.txt", &nStudents);
return 0;
}
The problem is that when I run the program, I get an error stating the sub scripted value is neither an array nor pointer. I am sort of new to this concept, so I am sort of don't understand what it means. If anyone can tell me what I am doing wrong, and how I can achieve the result that I want, I will be very great-full. Thank you.
In your program a is neither an array nor a pointer. It is of struct student type . You should declare a as an array of struct.
struct student a[SIZE];
a[i].firstName
This is array notation.
a.firstName
This is variable notation.
struct student a;
This is what you have. It's a variable.
struct student a[LEN];
This is what you need. It's an array.

Char array in a struct - incompatible assignment? [duplicate]

This question already has answers here:
Structure Problem in C
(12 answers)
Closed 4 years ago.
I tried to find out what a struct really 'is' and hit a problem, so I have really 2 questions:
1) What is saved in 'sara'? Is it a pointer to the first element of the struct?
2) The more interesting question: Why doesn't it compile?
GCC says "test.c:10: error: incompatible types in assignment" and I can't figure out why...
(This part has been solved by your answers already, great!)
#include <stdio.h>
struct name {
char first[20];
char last[20];
};
int main() {
struct name sara;
sara.first = "Sara";
sara.last = "Black";
printf("struct direct: %x\n",sara);
printf("struct deref: %x\t%s\n", *sara, *sara);
}
Thanks for your help!
This has nothing to do with structs - arrays in C are not assignable:
char a[20];
a = "foo"; // error
you need to use strcpy:
strcpy( a, "foo" );
or in your code:
strcpy( sara.first, "Sara" );
Or you could just use dynamic allocation, e.g.:
struct name {
char *first;
char *last;
};
struct name sara;
sara.first = "Sara";
sara.last = "Black";
printf("first: %s, last: %s\n", sara.first, sara.last);
You can also initialise it like this:
struct name sara = { "Sara", "Black" };
Since (as a special case) you're allowed to initialise char arrays from string constants.
Now, as for what a struct actually is - it's a compound type composed of other values. What sara actually looks like in memory is a block of 20 consecutive char values (which can be referred to using sara.first, followed by 0 or more padding bytes, followed by another block of 20 consecutive char values (which can be referred to using sara.last). All other instances of the struct name type are laid out in the same way.
In this case, it is very unlikely that there is any padding, so a struct name is just a block of 40 characters, for which you have a name for the first 20 and the last 20.
You can find out how big a block of memory a struct name takes using sizeof(struct name), and you can find out where within that block of memory each member of the structure is placed at using offsetof(struct name, first) and offsetof(struct name, last).
use strncpy to make sure you have no buffer overflow.
char name[]= "whatever_you_want";
strncpy( sara.first, name, sizeof(sara.first)-1 );
sara.first[sizeof(sara.first)-1] = 0;
sara is the struct itself, not a pointer (i.e. the variable representing location on the stack where actual struct data is stored). Therefore, *sara is meaningless and won't compile.
You can use strcpy to populate it. You can also initialize it from another struct.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct name {
char first[20];
char last[20];
};
int main() {
struct name sara;
struct name other;
strcpy(sara.first,"Sara");
strcpy(sara.last, "Black");
other = sara;
printf("struct: %s\t%s\n", sara.first, sara.last);
printf("other struct: %s\t%s\n", other.first, other.last);
}
The Sara structure is a memory block containing the variables inside. There is nearly no difference between a classic declarations :
char first[20];
int age;
and a structure :
struct Person{
char first[20];
int age;
};
In both case, you are just allocating some memory to store variables, and in both case there will be 20+4 bytes reserved. In your case, Sara is just a memory block of 2x20 bytes.
The only difference is that with a structure, the memory is allocated as a single block, so if you take the starting address of Sara and jump 20 bytes, you'll find the "last" variable. This can be useful sometimes.
check http://publications.gbdirect.co.uk/c_book/chapter6/structures.html for more :) .
You can try in this way. I had applied this in my case.
#include<stdio.h>
struct name
{
char first[20];
char last[30];
};
//globally
// struct name sara={"Sara","Black"};
int main()
{
//locally
struct name sara={"Sara","Black"};
printf("%s",sara.first);
printf("%s",sara.last);
}

Resources