Thread: Problem referencing structure elements by pointer

  1. #1
    Registered User
    Join Date
    May 2008
    Posts
    28

    Problem referencing structure elements by pointer

    Hi folks,

    I feel a little guilt coming here and only asking questions - hard for me to contribute to the community here much at the moment as I'm on a steep learning curve. A big thanks for all of the help I've had here so far. Hope you don't mind me asking further questions...

    I'm building a set of functions which are intended to read a set of configuration data from a .conf text-based file into a structure. I want a "getConfDataFromFile" function to fill the configuration structure such that I can use it something like this:-

    Code:
    struct configurationOptions thisProcessConfig;
    if ( getConfDataFromFile(&thisProcessConfig) ) {
     doYourThing();
    } else {
     bail("Couldn't load configuration file");
    }
    So far I have the following piece of code. The getStringFromConf and getIntFromConf have been tested and appear to work succesfully. My problem is with the loadConfigurationOptionsFromFile function, which gives the following errors on compile attempt:-

    Code:
    includes/configuration.h:45: error: request for member ‘host’ in something not a structure or union
    includes/configuration.h:46: error: request for member ‘host’ in something not a structure or union
    includes/configuration.h:50: error: request for member ‘port’ in something not a structure or union
    includes/configuration.h:51: error: request for member ‘port’ in something not a structure or union
    ... etc (they all fail).

    This is the full code, with the function causing me a problem highlighted in red:-

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <string.h>
    
    #include "defines.h"
    
    /* A structure to hold all of our configuration data */
    typedef struct  {
    	char 	host[16];
    	int		port;
    	char	adminHost[16];
    	int		adminPort;
    	int		logLevel;
    	int		selfConsumeMode;
    	ushort	queueSize;
    	char	pidFilePath[120];
    	int		persistMessages;
    } configurationOptions;
    
    
    /* Load up config options from conf file to supplied structure */
    int loadConfigurationOptions(struct configurationOptions *suppliedStructure) {
    	 
    	/* We need at least a host and port for the queue and for admins */
    	if (!getStringFromConf("host", suppliedStructure.host, sizeof suppliedStructure.host)) {
    		return(0);
    	}
    	
    	suppliedStructure.port = getIntFromConf("port");
    	if (suppliedStructure.port == 0) {
    		return(0);
    	}
    	
    	if (!getStringFromConf("adminhost", suppliedStructure.adminHost, sizeof suppliedStructure.adminHost)) {
    		return(0);
    	}
    	
    	suppliedStructure.adminPort = getIntFromConf("adminport");
    	if (suppliedStructure.adminPort == 0) {
    		return(0);
    	}
    
    	/* Anything missing from here on is non-critical and we'll use defaults if we can't load */
    	suppliedStructure.logLevel = getIntFromConf("loglevel");
    	if (suppliedStructure.logLevel == 0) {
    		suppliedStructure.logLevel = LOG_LEVEL_DEFAULT;
    	}
    
    	/* Defaults to zero (off) if the int fails to load */
    	suppliedStructure.selfConsumeMode = getIntFromConf("selfconsume");
    
    	suppliedStructure.queueSize = getIntFromConf("queuesize");
    	if (suppliedStructure.queueSize == 0) {
    		suppliedStructure.queueSize = QUEUE_SIZE;
    	}
    	
    	/* Maximum size of an IPC V queue is 65535 */
    	if (suppliedStructure.queueSize > 65535) {
    		suppliedStructure.queueSize = QUEUE_SIZE;
    	}
    	
    	if ( !getStringFromConf("pidfilepath", suppliedStructure.pidFilePath, sizeof (suppliedStructure.pidFilePath-1)) ) {
    		strcpy(suppliedStructure.pidFilePath, PID_FILE_PATH);
    	}
    
    	return(1);
    }
    
    int getStringFromConf(const char * searchkey, char *resultValue, size_t resultSize) {
    	int result, i = 0;
    	char c[120];
    	FILE *f = NULL;
    	f = fopen(CONF_FILE_PATH, "r");
    	if (f != NULL)  {
    
    		while ( fgets(c, 120, f) != NULL ) {
    			char *sep = "=";
    			char *key, *value = "";
    			key = strtok(c, sep);
    			value = strtok(NULL, sep);
    
    			if ( (value != NULL) && (strcmp(key, searchkey) == 0) ) {
    				if ( strlen(value) > resultSize-1 ) {
    					result = 0;
    					strncpy(resultValue, CONF_FILE_BUFFERSIZE_ERROR, resultSize);
    				} else {
    					strncpy(resultValue, value, resultSize);
    
    					/* remove any newlines */
    					for ( i = 0; i < 119; i++ ) {
    					    if ( resultValue[i] == '\n' ) {
    					        resultValue[i] = '\0';
            					break;
        					}
    }
    					result = 1;
    				}
    			}
    		}
    
    		fclose(f);
    
    	} else {
    		result = 0;
    		strncpy(resultValue, CONF_FILE_NOTFOUND_ERROR, resultSize);
    	}
    	return result;
    }
    
    /* Only to be used to fetch positive ints */
    int getIntFromConf(const char * searchkey) {
    	/* Returns either an positive integer value or -1 in event of error */
    	char charValue[10];
    	int j = -1;
    
    	if ( getStringFromConf(searchkey, charValue, 9) ) {
    		j = atoi(charValue);
    	}
    	return j;
    }
    Full code posted for completeness, although I have a feeling that my problem lies in the way that I'm trying to reference the supplied structure by pointer.

    Any shove in the right direction would be much appreciated......

  2. #2
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Use -> instead of . when dealing with pointers of structs. (Little more indepth than this, but this'll get you started.)

  3. #3
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    It's a pointer, so you want to dereference it first,
    Code:
    (*suppliedStructure).host
    or the shorthand way.
    Code:
    suppliedStructure->host

  4. #4
    Registered User
    Join Date
    May 2008
    Posts
    28
    Many thanks - that looks like it will correct my original code.

    How do I do the sizeof though, if suppliedStructure->host is actually a pointer to something (in which case will sizeof not consistently be a 4 byte int)?

    Thanks!

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by trillianjedi View Post
    How do I do the sizeof though, if suppliedStructure->host is actually a pointer to something (in which case will sizeof not consistently be a 4 byte int)?
    Yes, it will be the size of a pointer if you use sizeof on a pointer, but you aren't.
    You are using it on a char array (host), so you're alright.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    May 2008
    Posts
    28
    Thanks - I understand now. So the "->" actually de-references....

    I'm now getting different compiler errors :-

    Code:
    includes/configuration.h:67: error: dereferencing pointer to incomplete type
    Does this relate to my typing the struct in the function call parameters? I always though that was considered good practice, so I'm not sure why my compiler is complaining?

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You have not defined such a thing as a struct configurationOptions. You've defined an anonymous struct (which you obviously can't use as a parameter), and you've defined configurationOptions.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    What tabstop tries to explain is that there is no such thing as "struct configurationOptions", because you made the struct anonymous.
    However, you did give that anonymous a name -- configurationOptions. So just type "configurationOptions" instead of "struct configurationOptions".
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    May 2008
    Posts
    28
    OK - many thanks. The code now compiles, so that's fab and I'm grateful for your help.

    However, I'm left slightly confused as to why my structure is "anonymous"? My understanding (which appears incorrect) was that typedef acts to define my structure, and make it known thing rather than anonymous?

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Well, what I mean is that the struct (before the typedef happens) doesn't have its own name. (Like "struct whatever".)

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    That's the thing.
    A struct is defined as:
    Code:
    struct StructName
    {
    /* Contents */
    }
    In this case, the structure's name is actually StructName (but to create something of this, you have to type struct StructName).
    Now we can use a typedef:
    Code:
    typedef struct StructName StructName;
    ...to give it another name.
    But a struct can also be anonymous in the sense you don't give it a name:
    Code:
    struct
    {
    /* Contents */
    }
    Anonymous struct.
    We can combine the typedef with the anonymous struct to give the anonymous struct a name, which is what you did.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    May 2008
    Posts
    28
    OK - my intention is that this is a structure which is known as a "configurationOptions" structure. Is my typedef somehow inccorect?

    Thanks again for you help.

    Code:
    typedef struct  {
    	char 	host[16];
    	int		port;
    	char	adminHost[16];
    	int		adminPort;
    	int		logLevel;
    	int		selfConsumeMode;
    	ushort	queueSize;
    	char	pidFilePath[120];
    	int		persistMessages;
    } configurationOptions;

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    No, it's correct. It is known as "configurationOptions", not "struct configurationOptions".
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Examples:
    An anonymous struct:
    Code:
    struct {
        int var1;
        float var2;
    } foo;
    foo is a variable of a type that can't be named (hence anonymous).
    A struct configurationOptions would be
    Code:
    struct configurationOptions {
        char host[16];
        int port;
        char etcetera;
    }
    What you have done is taken the first struct (an anonymous one) and typedef'ed it to the name "configurationOptions" (without the struct). So it's a struct that is known as configurationOptions, not as "struct configurationOptions".

  15. #15
    Registered User
    Join Date
    May 2008
    Posts
    28
    Aha! Lightbulb moment.....

    Thanks - you've clarified that for me greatly.

    So the next natural question is have I done this the right way? So I have an anonymous structure which is typedef'd to the name configurationOptions. Taking the "struct" out of my function will let that compile.

    However, the requirement for using this function is that I hand the function a pointer to the configurationsOptions anonymous structure. As it's anonymous, any declarations would be of something of unknown size wouldn't they?

    Added - here's what I mean, the following code gives a "storage size of ‘tmpbuf’ isn’t known" error:-

    Code:
    	struct configurationsOptions tmpbuf;
    	if ( !loadConfigurationOptions(&tmpbuf) ) {
    		return(0);
    	}
    For my usage of this structure in this way, do I need to ensure that it is not anonymous ?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 0
    Last Post: 03-20-2008, 07:59 AM
  2. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  3. accessing structure pointer problem
    By godhand in forum C Programming
    Replies: 2
    Last Post: 04-09-2004, 10:52 PM
  4. Pointer to structure problem
    By unregistered in forum C Programming
    Replies: 3
    Last Post: 12-24-2001, 07:54 AM
  5. C structure within structure problem, need help
    By Unregistered in forum C Programming
    Replies: 5
    Last Post: 11-30-2001, 05:48 PM