LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-25-2019, 07:05 AM   #1
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth? I would say I hope so but I'm not so sure about that... I could just be a figment of your imagination too.
Distribution: Currently OpenMandriva. Previously openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,071

Rep: Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574
Question Some questions about C structures and pointers


As the thread title says; I have some questions about both structures and pointers. While a pointer isn't a structure and vice versa; I figured rather than starting two separate threads, and since one can use pointers with structures, I'll use the one thread instead of two.

I'll start off with my "structure questions" since they seem to feature quite a bit in almost all other code I've tried to read...

But first, I'll start off with what I think I do get about them (feel free to correct me if I'm wrong); a structure is basically a symbolic name for a group of variables that are related to the same "entity", a structure has "member variables". So basically, if I create a structure called "now", and I have a member called "today", without using pointers with it, to access/write it, it would look like now.today

So now on to my question; Does the line below from this code specify three structures called now, target and rel? Because it just isn't clear to me if that's referring to structures or the member variables.

Code:
struct timespec now, target, rel;
particularly with the following below the above line;

Code:
if (clock_gettime(clockid, &now))
		return UNSUPPORTED;
	target = timespec_add(now, ns);

	if (clock_nanosleep(clockid, TIMER_ABSTIME, &target, NULL))
		return UNSUPPORTED;
	clock_gettime(clockid, &now);
I know the & is the address operator, and I know what a return and if statement is, but the above is still confusing to me.

Now on to my "pointer questions"...

Again, I think I know basically what a "pointer" is, in that it's a variable that contains a memory address, being the memory address of what it's being pointed to. Again, feel free to correct me if I'm wrong.

Does the highlighted part of the code below mean "pointer to a char", and if so, is that all it means, in that: it just points to a char? And why would I include that part, as it just isn't making sense to me why that needs to be there.

Code:
str = (char *) malloc(15);
And yes, I think I know what "type casting" is as well, but I don't get why one would "type cast" a pointer though.

Thanks in advance for any help with this.

James
 
Old 09-25-2019, 07:47 AM   #2
rtmistler
Moderator
 
Registered: Mar 2011
Location: MA, USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 8,038
Blog Entries: 13

Rep: Reputation: 3488Reputation: 3488Reputation: 3488Reputation: 3488Reputation: 3488Reputation: 3488Reputation: 3488Reputation: 3488Reputation: 3488Reputation: 3488Reputation: 3488
For the first part, you need to remember the line:
Code:
struct timespec now, target, rel;
This means that "now", "target", and "rel" are ALL timespec structures. They are not pointers to structures, they are structures.

When you review that code and it confuses you, I have to inquire why, or rather how far did you examine the code and research it? That code is using functions, which appear to be typical library functions that you could look up: clock_gettime(), timespec_add(), clock_nanosleep(). Research what the prototypes of those functions are, and you'll see that some of them expect a timespec structure pointer, and some of them expect a timespec structure. That is how those functions were written, and the code you're reading is adhering to the prototypes for these functions. Nothing more.

For the next question, please look up the prototype for the function malloc(). What type of pointer would it return? Here, the variable "str" is most likely a char * type of variable, and so the writer of that line of code, is casting the result from the malloc() function, into the correct pointer type which they need it to be. They are being strict about things, and this is fine. It is also fine, to not perform the cast, it is merely less "language strict syntax" if you do not.
 
2 members found this post helpful.
Old 09-25-2019, 07:59 AM   #3
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,508

Rep: Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811
Quote:
Originally Posted by jsbjsb001 View Post
Code:
str = (char *) malloc(15);
And yes, I think I know what "type casting" is as well, but I don't get why one would "type cast" a pointer though.
I think you asked this before. C FAQ 7.7 - Why does some code carefully cast the values returned by malloc to the pointer type being allocated?
 
2 members found this post helpful.
Old 09-25-2019, 09:49 AM   #4
hazel
Senior Member
 
Registered: Mar 2016
Location: Harrow, UK
Distribution: LFS, AntiX, Slackware
Posts: 3,378
Blog Entries: 9

Rep: Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884
A pointer points to a variable and this variable has a type, so the pointer has a type. The address stored in the pointer only tells the computer where to start reading the variable; it doesn't tell it where to stop. That will be determined by the type. A pointer to a timespec structure will have the timespec type. When reading (dereferencing) the pointer, the computer will read n bytes where n=sizeof(timespec).

Strictly speaking, you don't have to typecast a pointer returned by malloc() because it will automatically be given the type of the pointer variable you assign it to. However it's good practice to give the pointer an explicit type. It makes the program easier to read and also ensures that you are given a warning if you accidentally assign it to the wrong variable!

Last edited by hazel; 09-25-2019 at 09:51 AM.
 
3 members found this post helpful.
Old 09-27-2019, 02:20 AM   #5
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth? I would say I hope so but I'm not so sure about that... I could just be a figment of your imagination too.
Distribution: Currently OpenMandriva. Previously openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,071

Original Poster
Rep: Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574
Thanks guys, and thank you very much for your explanation Hazel! That's one of the things I was wondering, and just wasn't making sense to me.

The "str" in the line I posted in post #1 was from this code for malloc(). As you will see, "str" is already declared as a "char pointer", that's why I was asking why it was still type casted anyway. And yes RT, I wasn't thinking they were "pointers to structures", but I just wasn't sure if they were actual structures, or simply just structure members.

So in regards to structures; would it be right to say that if something is proceeded by the address operator, and it's in a declaration for a structure, then it means it's an actual structure, and not just a structure member? (like &target in my OP for example, in that; "target" IS an actual structure, and not just a member of a structure)

In regards to pointers, and in simple terms; would it be correct to say that ntubski's link is saying that, because malloc() returns a "void pointer", that's why if you want to allocate memory for say an int, then you have to type cast it?

Also, I was practicing returns from functions, as well as using pointers with functions in the code below as you'll see. While I have fixed it so gcc stops complaining and compiles the code below; I would like to ask if my understanding of the problem is correct. Now basically if I uncomment the line commented out, and comment the lines highlighted in bold below, it compiles and works as intended. The only difference between the code I'm referring to is that the non-working lines where I'm pointing my pointers to v1 and v2, is that, my pointers ptr1 and ptr2 have an asterisk in front of them.

Code:
#include <stdio.h>

int myfunction(int return_stat);
int ptrfunction(int *ptr1, int *ptr2);

static int vl1 = 1000;

int main(void) {
    
   // int enteredNumber = 0, func_return = 0, v1 = 0, v2 = 0, *ptr1 = &v1, *ptr2 = &v2;
    int enteredNumber = 0, func_return = 0, v1 = 0, v2 = 0, *ptr1, *ptr2 ;
    *ptr1 = &v1;
    *ptr2 = &v2; 
    
    puts("Enter return status: ");
    scanf("%i", &enteredNumber);
    puts("Calling myfunction()");
    func_return =  myfunction(enteredNumber) ;
    puts("Returned to main()");
    printf("myfunction returned %i\n", func_return);
    
    printf("\n\nv1 = %i\nv2 = %i\nptr1 = %i\nptr2 = %i\n", v1, v2, *ptr1, *ptr2);
    printf("ptr1 address: %p\nptr2 address: %p\n", ptr1, ptr2);
    printf("vl1 = %i\n", vl1);
    puts("Calling ptrfunction");
    ptrfunction(ptr1, ptr2);
    puts("\nReturned to main()");
    printf("v1 = %i\nv2 = %i\nptr1 = %i\nptr2 = %i\n", v1, v2, *ptr1, *ptr2);
    printf("ptr1 address: %p\nptr2 address: %p\n", ptr1, ptr2);
    
    return 0;
}

    int myfunction(int return_stat) {

    printf("\nmyfunction is returning: %i\n", return_stat);
    
    return return_stat;
}

    int ptrfunction(int *ptr1, int *ptr2) {
        
    ptr2 = &vl1;
        
    puts("\nEntered ptrfunction");
    printf("ptr1 = %d\nptr2 = %d\n", *ptr1, *ptr2);
    *ptr1 = 100;
    *ptr2 = 101;
    printf("ptr2 = %d\n", *ptr2);
    printf("ptr1 address: %p\nptr2 address: %p\n", ptr1, ptr2);
   // puts("Enter two values: ");
   // scanf("%i %i", ptr1, ptr2);
    
    return 0;
}
If I try and compile that, I get the following errors below. But if I fix it like I said above, there's no problems.

Code:
james@jamespc: practice> gcc -g -Wall -Werror func_return_prac.c -o func_return_prac
func_return_prac.c: In function ‘main’:
func_return_prac.c:12:11: error: assignment to ‘int’ from ‘int *’ makes integer from pointer without a cast [-Werror=int-conversion]
   12 |     *ptr1 = &v1;
      |           ^
func_return_prac.c:13:11: error: assignment to ‘int’ from ‘int *’ makes integer from pointer without a cast [-Werror=int-conversion]
   13 |     *ptr2 = &v2;
      |           ^
func_return_prac.c:12:11: error: ‘ptr1’ is used uninitialized in this function [-Werror=uninitialized]
   12 |     *ptr1 = &v1;
      |     ~~~~~~^~~~~
func_return_prac.c:13:11: error: ‘ptr2’ is used uninitialized in this function [-Werror=uninitialized]
   13 |     *ptr2 = &v2;
      |     ~~~~~~^~~~~
cc1: all warnings being treated as errors
While I think I get why I get the last two errors, it's the first two errors highlighted in bold that I'm not quite sure about. So my question is: is it saying in plain simple english that; because I've used the asterisk in front of ptr1 and ptr2 (my two pointers), I'm telling gcc to "convert" ptr1 and ptr2 from pointers to integers ? Because that's one of gcc's errors that's just mindboggling to me.
 
Old 09-27-2019, 03:46 AM   #6
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 13,070

Rep: Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132
ptr1 = &v1;
means: take the address of variable v1 and put it into the variable ptr1
*ptr1 = &v1;
means: take the address of variable v1 and put it into the memory location pointed by variable ptr1
in this case ptr1 is still uninitialized and points to an integer, not a pointer (how it was declared). That's why you got two error messages.
 
1 members found this post helpful.
Old 09-27-2019, 05:26 AM   #7
hazel
Senior Member
 
Registered: Mar 2016
Location: Harrow, UK
Distribution: LFS, AntiX, Slackware
Posts: 3,378
Blog Entries: 9

Rep: Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884
Quote:
Originally Posted by jsbjsb001 View Post
So in regards to structures; would it be right to say that if something is proceeded by the address operator, and it's in a declaration for a structure, then it means it's an actual structure, and not just a structure member? (like &target in my OP for example, in that; "target" IS an actual structure, and not just a member of a structure)
Code:
Structure: this_struct
Structure member: this_struct.field1
Pointer to structure: pointer = &this_struct
Structure member: pointer->field.1
Fields are prefixed by a dot when refering to the actual structure and an arrow when refering to a pointer to a structure.
Quote:
In regards to pointers, and in simple terms; would it be correct to say that ntubski's link is saying that, because malloc() returns a "void pointer", that's why if you want to allocate memory for say an int, then you have to type cast it?
"Void pointer" is just a jocular name for a pointer without an assigned type. Malloc() always returns a void pointer because the people who wrote it have no way of knowing what you want to use the reserved space for. You convert the void pointer to one of specific type either by typecasting it explicitly or by assigning it to a pointer variable of that type.
 
1 members found this post helpful.
Old 09-27-2019, 08:17 AM   #8
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth? I would say I hope so but I'm not so sure about that... I could just be a figment of your imagination too.
Distribution: Currently OpenMandriva. Previously openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,071

Original Poster
Rep: Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574
Quote:
Originally Posted by pan64 View Post
ptr1 = &v1;
means: take the address of variable v1 and put it into the variable ptr1
*ptr1 = &v1;
means: take the address of variable v1 and put it into the memory location pointed by variable ptr1
in this case ptr1 is still uninitialized and points to an integer, not a pointer (how it was declared). That's why you got two error messages.
So just to make sure I understand you, let's say ptr1 is stored at address 2 and v1 is stored at address 3 (completely made up addresses I know); in the first line (ptr1 = &v1), the value of ptr1 would be "3" (pointing to v1). In the second case (*ptr1 = &v1), the value of ptr1 would be "2"? Is that right?

Quote:
Originally Posted by hazel View Post
...
"Void pointer" is just a jocular name for a pointer without an assigned type. Malloc() always returns a void pointer because the people who wrote it have no way of knowing what you want to use the reserved space for. You convert the void pointer to one of specific type either by typecasting it explicitly or by assigning it to a pointer variable of that type.
So you're saying that if I didn't type cast the pointer malloc() gives you, you would setup a pointer where you would give it a data type like int, or whatever else?
 
Old 09-27-2019, 08:27 AM   #9
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,508

Rep: Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811Reputation: 1811
Quote:
Originally Posted by jsbjsb001 View Post
In regards to pointers, and in simple terms; would it be correct to say that ntubski's link is saying that, because malloc() returns a "void pointer", that's why if you want to allocate memory for say an int, then you have to type cast it?
void pointers are special in that you don't have to cast in order to convert them to another pointer type (but some people like to put the cast in anyway).
 
1 members found this post helpful.
Old 09-27-2019, 08:31 AM   #10
hazel
Senior Member
 
Registered: Mar 2016
Location: Harrow, UK
Distribution: LFS, AntiX, Slackware
Posts: 3,378
Blog Entries: 9

Rep: Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884
Quote:
Originally Posted by jsbjsb001 View Post
So you're saying that if I didn't type cast the pointer malloc() gives you, you would setup a pointer where you would give it a data type like int, or whatever else?
You have to give it a data type one way or another, otherwise it can't be dereferenced. Remember, to read data, the computer has to know where to start and where to stop. The address stored in the pointer tells it where to start; the pointer type tells it where to stop.

You can provide the type either by typecasting explicitly or by assigning the returned value to a pointer variable whose type you have already declared. If that variable is an integer pointer, then yes, the returned address becomes that of an integer pointer.

If you give your pointer the wrong type using either method, the compiler won't know that it's wrong so you won't get an error message. But your program will probably crash and burn!
 
1 members found this post helpful.
Old 09-27-2019, 08:59 AM   #11
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 13,070

Rep: Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132
Quote:
Originally Posted by jsbjsb001 View Post
So just to make sure I understand you, let's say ptr1 is stored at address 2 and v1 is stored at address 3 (completely made up addresses I know); in the first line (ptr1 = &v1), the value of ptr1 would be "3" (pointing to v1). In the second case (*ptr1 = &v1), the value of ptr1 would be "2"? Is that right?
No. The first case is ok, but the second case is not ok:
in this case the value of ptr1 is not changed, but the location where ptr1 points to (which was not set in your code).
 
Old 09-27-2019, 09:02 AM   #12
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth? I would say I hope so but I'm not so sure about that... I could just be a figment of your imagination too.
Distribution: Currently OpenMandriva. Previously openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,071

Original Poster
Rep: Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574
While I think I understand most of what you're saying Hazel; I'm not quite sure how I would give the pointer the wrong data type. I think I get what you mean by type casting it, but in terms of the other way to do it; I'm not quite sure I'm understanding you correctly.

So for example; if I had a call to malloc() like *somePointer = malloc(15); that I've say already declared as an int, then given I've already declared it as an int; how would I pick the wrong data type? Sorry if that doesn't make much sense - I don't know how else to ask what I'm trying to ask. Do you have an example of say a correct way, and a wrong way in terms of what you're referring to, that involves the "other way" to do it without explicitly type casting a variable?
 
Old 09-27-2019, 09:05 AM   #13
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth? I would say I hope so but I'm not so sure about that... I could just be a figment of your imagination too.
Distribution: Currently OpenMandriva. Previously openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,071

Original Poster
Rep: Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574Reputation: 1574
Quote:
Originally Posted by pan64 View Post
No. The first case is ok, but the second case is not ok:
in this case the value of ptr1 is not changed, but the location where ptr1 points to (which was not set in your code).
I'm not sure I'm following what you say there. Sorry pan, but I'm not understanding what exactly you mean.
 
Old 09-27-2019, 09:30 AM   #14
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 13,070

Rep: Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132Reputation: 4132
int *ptr1; means ptr1 is a pointer and (as a variable) contains an address of an integer.
ptr1 = &v1; means ptr1 (as variable) will be set to hold the address of variable v1 (which is actually an integer).
Now *ptr1 will be an integer, exactly the same as v1. Assigning anything to *ptr1 is equal to assign it to v1. For example *ptr1 = 5; and v1 = 5; are identical operations (in this case). And again, assigning anything to *ptr1 will not modify the variable ptr1 itself, but the location where ptr1 points to (like v1 in our example).
But in your code (post #5) ptr1 (and ptr2) are not set/initialized, so noone knows where ptr1 points to. Therefore *ptr1 is unknown.
 
Old 09-27-2019, 09:34 AM   #15
hazel
Senior Member
 
Registered: Mar 2016
Location: Harrow, UK
Distribution: LFS, AntiX, Slackware
Posts: 3,378
Blog Entries: 9

Rep: Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884Reputation: 1884
Quote:
Originally Posted by jsbjsb001 View Post
While I think I understand most of what you're saying Hazel; I'm not quite sure how I would give the pointer the wrong data type. I think I get what you mean by type casting it, but in terms of the other way to do it; I'm not quite sure I'm understanding you correctly.

So for example; if I had a call to malloc() like *somePointer = malloc(15); that I've say already declared as an int, then given I've already declared it as an int; how would I pick the wrong data type?
You know inside your head what type of data a pointer is supposed to point to but gcc has no way of knowing that unless you tell it. Now suppose you have used malloc to reserve some space for a previously defined type of structure, let's call it mystruct. malloc(sizeof(mystruct)) will reserve exactly the right amount of space. It will return a void pointer which you can store in a mystruct pointer.
Code:
mystruct *mystruct_pointer;
mystruct_pointer = malloc(sizeof(mystruct);
But suppose you have another pointer variable called struct_pointer which has actually been declared as a different kind of pointer altogether. The names are very similar, so you could carelessly write
Code:
struct_pointer = malloc(sizeof(mystruct));
gcc won't know that you've made a mistake because what you have written is syntactically correct. However, when it comes to dereference that pointer, it will read the number of bytes appropriate to whatever type of pointer struct_pointer is. This may be more or less than the size of the reserved area. If it's more, some garbage will be read in addition to the reserved area. If less, some of the data won't get read at all. Either way your program will probably crash.

Now if you typecast the return from malloc, you get:
Code:
struct_pointer = (mystruct)malloc(sizeof(mystruct));
And gcc will think, "Hang on! struct_pointer isn't of the type mystruct so why has it been set to house a mystruct pointer?" And it will give you a pointer mismatch warning that will alert you to your mistake. That's why I think you should typecast your pointers.
 
  


Reply

Tags
c programming, pointers, structures


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Need help with pointers to structures schmitta Programming 2 01-21-2014 12:33 PM
[SOLVED] array of structures in c, and function pointers. I need a structured approach. karinier Linux - Newbie 1 08-31-2013 01:16 PM
[SOLVED] Could I get some pointers on pointers please? theKbStockpiler Programming 46 05-18-2010 12:30 AM
Pointers Pointers Pointers urzumph Programming 9 03-11-2004 09:49 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:18 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration