Printing Address of Struct Element - pointers

I have the following struct:
typedef struct Author
{
char** novels;
} Author;
And I want to print the address of an element in the novels array. I tried these two:
printf("%p\n", &(herbert->novels[1]));
printf("%p\n", herbert->novels[1]);
But I'm not sure which is correct. Can someone help me understand which to use and why?

Take a look at the below...
typedef struct Author
{
char** novels;
} Author;
int main()
{
Author a;
char b = 'b';
a.novels = new char*[2];
a.novels[0] = NULL;
a.novels[1] = NULL;
printf("1. %p\n", a.novels[1]);
printf("2. %p\n", &(a.novels[1]));
delete[] a.novels;
return 0;
}
this outputs the following
1. 0000000000000000
2. 00000000001269C8
You can see the first print is actually a NULL - which is the value stored at the a.novels[1].
The second is the address of the a.novels[1] memory.
Assuming you look for the memory address of the item, you'll need the second syntax
printf("%p\n", &(herbert->novels[1]));

Related

why my my function is using call by value method?

I don't know why in last line it is printing data of first element instead of last element. I want explanation.
// A simple C program for traversal of a linked list
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
// This function prints contents of linked list starting from
// the given node
void printList(struct Node* n)
{
while (n != NULL) {
printf(" %d ", n->data);
n = n->next;
}
}
int main()
{
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
// allocate 3 nodes in the heap
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
head->data = 1; // assign data in first node
head->next = second; // Link first node with second
second->data = 2; // assign data to second node
second->next = third;
third->data = 3; // assign data to third node
third->next = NULL;
printList(head);
printf("%d",head->data);
return 0;
}
As the function is accepting pointers so it should be call by reference.
And in last loop of function when n pointer is equal to NULL.
But in last line of this code is printing data of first list of my linked list.
Actually what you are doing is not being done in the actual linked list, it not pass by reference
void printList(struct Node* n)
{
/* some code here */
}
void main()
{
/* all your code here */
printList(head);
}
so if you want to change the head in the actual linked list you will have to pass the address of the pointer head to the function
something like this
int append_list(node **head, int data)
{
while((*head)->next!=NULL)
{
(*head) = (*head)->next;
}
}
int main()
{
struct node *head = NULL;
/* add nodes */
print_list(&head);
}
so here is the modification in your code:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
// This function prints contents of linked list starting from
// the given node
void printList(struct Node** n)
{
while ((*n)->next != NULL) {
printf(" %d ", (*n)->data);
(*n) = (*n)->next;
}
}
int main()
{
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
// allocate 3 nodes in the heap
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
head->data = 1; // assign data in first node
head->next = second; // Link first node with second
second->data = 2; // assign data to second node
second->next = third;
third->data = 3; // assign data to third node
third->next = NULL;
printList(&head);
printf("%d",head->data);
return 0;
}
here the output will be
1 2 3
since you have used (*head) for the traversal you no longer have the access to your list and hence will get segmentation fault if you try to access
(*head)->next
But I would not suggest to do this since now you will not be able to deallocate the memory
There is no pass-by-reference in C, everything is pass-by-value. People use pointers to emulate pass-by-reference, and this works because you can use the passed-in pointer to get at the same underlying data item.
In other words, even though the passed-in pointer is a pass-by-value copy within the function, the fact that it has the same value as the original means that both point to the same thing.
However, if the thing you're trying to change is a pointer already, you need a pointer to a pointer to do this emulation.
I could give you the code to do this but, believe me, it's not want you want. It would mean that the list printing code would be destructive to the list itself, since the head would now point to NULL.
Here is some code instead which shows how to do something similar, one that uses this double-pointer method to change the pointer outside of the function:
#include <stdio.h>
#include <stdlib.h>
void allocateSomeMem(void **pPtr, size_t sz) {
*pPtr = malloc(sz);
}
int main(void) {
void *x = NULL;
printf("%p\n", x);
allocateSomeMem(&x, 42);
printf("%p\n", x);
}
You can see by the output that the pointer is being changed:
(nil)
0x55f9ce5f96b0
Now, obviously, you wouldn't do this for the simple example shown, it would be far easier just to return the new pointer and have it assigned to x. But this is just illustrative of the method to use.

why fgets() not working here?

In the below code scanf() is working for getting the name from the user but fgets() is not working pls someone help me to understand why it's not working
#include <stdio.h>
#include <stdlib.h>
typedef struct university{
int roll_no;
char name[16];
}uni;
int main()
{
uni *ptr[5],soome;char i,j=0;
for(i=0;i<5;i++)
{
ptr[i]=(uni*)calloc(1,20);
if(ptr[i]==NULL)
{
printf("memory allocation failure");
}
printf("enter the roll no and name \n");
printf("ur going to enter at the address%u \n",ptr[i]);
scanf("%d",&ptr[i]->roll_no);
//scanf("%s",&ptr[i]->name);
fgets(&ptr[i]->name,16,stdin);
}
while(*(ptr+j))
{
printf("%d %s\n",ptr[j]->roll_no,ptr[j]->name);
j++;
}
return 0;
}
First of all, fgets(char *s, int n, FILE *stream) takes three argument: a pointer s to the beginning of a character array, a count n, and an input stream.
In the original application you used the address operator & to get the pointer not to the first element of the name[16] array, but to something else (to use the address operator, you should have referenced the first char in the array: name[0]).
You use a lot of magic numbers in your application (e.g. 20 as the size of the uni struct). In my sample I'm using sizeof as much as possible.
Given that you use calloc, I've used the fact that the first parameter is the number of elements of size equal to the second parameter to preallocate all the five uni struct at once.
Final result is:
#include <stdio.h>
#include <stdlib.h>
#define NUM_ITEMS (5)
#define NAME_LENGTH (16)
typedef struct university{
int roll_no;
char name[NAME_LENGTH];
} uni;
int main()
{
uni *ptr;
int i;
ptr = (uni*)calloc(NUM_ITEMS, sizeof(uni));
if(NULL == ptr) {
printf("memory allocation failure");
return -1;
}
for(i=0; i<NUM_ITEMS; i++) {
printf("enter the roll no and name \n");
printf("You're going to enter at the address: 0x%X \n",(unsigned int)&ptr[i]);
scanf("%d",&ptr[i].roll_no);
fgets(ptr[i].name, NAME_LENGTH, stdin);
}
for(i=0; i<NUM_ITEMS; i++) {
printf("%d - %s",ptr[i].roll_no,ptr[i].name);
}
free(ptr);
return 0;
}
Note: I've added a call to free(ptr); to free the memory allocated by calloc at the end of the application and a different return code if it's not possible to allocate the memory.

trying to scanf value in a function to a struct inside a struct with a pointer

just look at the code please , says it all
#include<stdio.h>
#include<string.h>
struct DOB
{
int y,m,d;
}typedef DOB_t;
struct Courses
{
char* NameofCourse;
char* Lec;
int CourseID;
}typedef Course_t;
struct Student
{
char Name[20];
float Grade;
DOB_t dob;
Course_t Courses;
}typedef Student_t;
void addstudent(Student_t* s);
void addDate(DOB_t* dob);
void addCourse(Course_t* c);
main()
{
int opt;
Student_t s;
printf("Please choose one of the options:\n");
printf("<<<<<1.add student>>>>>\n<<<<<2.print student>>>>>\n");
scanf("%d",&opt);
switch(opt)
case 1:
{
addstudent(&s);
break;
}
}
void addstudent(Student_t* s)
{
printf("Enter student's name: ");
scanf("%s",s->Name);
printf("Enter Grade: ");
scanf("%.2f",s->Grade);
printf("Enter DateOfBirth: ");
***addDate(&(s->dob));***
addCourse(&(s->Courses));
}
void addDate(DOB_t* dob)
{
***scanf("%d %d %d", dob->d,dob->m,dob->y);***
}
void addCourse(Course_t* c)
{
printf("Enter Course Name And Lec Name: ");
scanf("%s %s",c->NameofCourse,c->Lec);
printf("Enter Course ID: ");
scanf("%d",c->CourseID);
}
it's not finished yet , but look at the highlighted row - i get an error when i'm triyng to scan values of DateofBirth using pointers into (s->DOB ) to keep the data in the value after function closes.
hope you understand my problem.
scanf requires you to pass the address of the memory space you want to store the result in. In your functions, wherever you are passing pointer to the structure,you should use scanf like this.
void addDate(DOB_t* dob)
{
scanf("%d %d %d", &dob->d,&dob->m,&dob->y); //This would read an integer into the address of pointer plus the offset of member into the structure.
}
You have make this change in your code at every place where you are reading values into structure pointer.

Need help copying a char array into an array struct with char pointer

I'm trying to copy char array word to char pointer s[1].c, an then another word to char pointer s[2].c but when i'm trying to do that , the second word appears to be copied in all two pointers . How can i fix that ? I don't want to use strings .
struct Stud {
char *c;
} s[100];
char word[32];
int main()
{
strcpy(word,"one");
s[1].c=word;
word={0};
strcpy(word,"two");
s[2].c=word;
cout<<s[1].c<<" "<<s[2].c;
return 0;
}
In your code you are setting s[1].c = word; which means you are setting s[1].c to the address of word. Then you set s[2].c = word; which is the same exact memory location. (With c strings, (char *)s1 = (char *)2 does not do a string copy as you might expect. It just assigns one pointer to another).
With strdup you allocate a new memory block and then copy the string into the allocated space.
Here's your code modified.
struct Stud
{
char *c;
} s[100];
int main()
{
char word[32];
strcpy(word, "one");
s[0].c = strdup(word); // In C/C++ the first array index is 0
strcpy(word, "two");
s[1].c = strdup(word);
// Should check to make sure s[0].c and s[1].c are not NULL....
cout << s[0].c << " " <<s [1].c;
free(s[0].c);
free(s[1].c);
return 0;
}

Pointers to stack

I am sorry that I cannot support my question with some code (I didnt understand how to structure it so it would be accepted here), but I try anyway.
If I understand correctly, a struct that references a struct of same type would need to do this with contained pointer for reference. Can this pointer reference to allocated space on the stack (instead of the heap) without creating segmentation fault? -
how should this be declared?
Yes, you can use pointers to variables on the stack, but only when the method that provides that stack frame has not returned. For example this will work:
typedef struct
{
int a;
float b;
} s;
void printStruct(const s *s)
{
printf("a=%d, b=%f\n", s->a, s->b);
}
void test()
{
s s;
s.a = 12;
s.b = 34.5f;
printStruct(&s);
}
This will cause an error however, as the stack frame would have disappeared:
s *bad()
{
s s;
s.a = 12;
s.b = 34.5f;
return &s;
}
EDIT: Well I say it will cause an error, but while calling that code with:
int main()
{
test();
s *s = bad();
printStruct(s);
return 0;
}
I get a warning during compilation:
s.c:27:5: warning: function returns address of local variable [enabled by default]
and the program appears to work fine:
$ ./s
a=12, b=34.500000
a=12, b=34.500000
But it is, in fact, broken.
You didn't say what language you are working in, so assuming C for now from the wording of your question... the following code is perfectly valid:
typedef struct str_t_tag {
int foo;
int bar;
struct str_t_tag *pNext;
} str_t;
str_t str1;
str_t str2;
str1.pNext = &str2;
In this example both str1 and str2 are on the stack, but this would also work if either or both were on the heap. The only thing you need to be careful of is that stack variables will be zapped when they go out of scope, so if you had dynamically allocated str1 and passed it back out of a function, you would not want str1->pNext to point to something that was on the stack within that function.
In other words, DON'T DO THIS:
typedef struct str_t_tag {
int foo;
int bar;
struct str_t_tag *pNext;
} str_t;
str_t *func(void)
{
str_t *pStr1 = malloc(sizeof(*pStr1));
str_t str2;
pStr1->pNext = &str2;
return pStr1; /* NO!! pStr1->pNext will point to invalid memory after this */
}
Not sure if this is specifically a C/C++ question, but I'll give C/C++ code as example in anyway.
The only way you can declare it: (with minor variations)
typedef struct abc
{
struct abc *other;
} abc;
other can point to an object on the stack as follows:
abc a, b; // stack objects
b.other = &a;
This is not a question about scope, so I'll skip commenting on possible issues with doing the above.
If, however, you want to assign it to a dynamically created object, there's no way this object can be on the stack.
abc b;
b.other = malloc(sizeof(abc)); // on the heap

Resources