Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Ask 4 help 2

Status
Not open for further replies.

maur3r

Technical User
Aug 28, 2006
34
PL
what does mean *(char* const*)random_name??
Is it a pointer to a pointer-to-a-pointer to char?
 
Well I have to say... I've never really seen anything like that before.

If you give a little more context about how random_name is declared and the exact code of how it's used, it might be easier to figure out.

const char* means you can set the pointer, but you can't modify the char* string that it's pointing to.
char* const means you can modify the char* string, but you can't change the pointer value.

I have no idea why you've got char* const*? The * after the const doesn't look right to me.

Everything inside the parenthesis is being de-referenced.

That's all I can tell from your post.
 
Here goes:

A char *const * is a (non-constant) pointer to a char *const.

A char *const is a constant pointer to a char.

A char is... well, you know what a char is. But note that we're talking about a non-constant char.

Code:
[COLOR=green]/* These illustrate the concept */[/color]
char            c = 'x';
char *const     p = &c;
char *const *   q = &p;

[COLOR=green]/* These are extras */[/color]
char            c2 = '5';
char *const     p2 = &c2;

Given that code, the following describes what you can and can't do with q:
Code:
[COLOR=green]/* These are ok */[/color]
**q = 'z'; [COLOR=green]/* Modifying the character */[/color]
q = &p2; [COLOR=green]/* Modifying q to point elsewhere*/[/color]

[COLOR=red]/* This isn't ok */[/color]
*q = &c2; [COLOR=red]/* ERROR: Modifying the pointed-to ([b]const[/b]) pointer */[/color]


Note also that you can point [tt]q[/tt] at a regular, non-const char*, just like you can point a const int* at a plain ol' int. So in the above code, [tt]p[/tt] and [tt]p2[/tt] could have been declared simply as char *. The same rules as above would apply to [tt]q[/tt], (though you could change [tt]p[/tt] and [tt]p2[/tt] directly).

You could not, however, declare them as const char * or const char * const. The type of [tt]q[/tt] says that, through it, you get to modify the character ultimately pointed to, so it can't point to anything through which it wouldn't be able to do so.


Now, as for the code you've posted, someone is casting [tt]random_name[/tt] to the type we've been talking about ([tt]q[/tt]'s type). Then, they're dereferencing it to a char *const.

So the dereferenced type is a constant; it can't point anywhere else in memory, and is stuck forever pointing at something. You can modify the character it points to, though.

So:
Code:
[COLOR=green]/* Given this: */[/color]
void * random_name = something();
char c3 = 'M';
char *const  p3 = *(char* const*)random_name;

[COLOR=green]/* You can do this */[/color]
*p3 = '@'; /* Modify the pointed-to character */

[COLOR=red]/* But not this */[/color]
p3 = &c3; [COLOR=red]/* ERROR: Modifying a const pointer */[/color]
 
I think I get it now (after adding some parentheses)...

const char* is basically: (const char)* i.e. const is applied to the chars being pointed to.

char* const is basically: (char*) const i.e. const is applied to the pointer, not the data.

const char* const is basically: (const char)* const i.e. The first two combined.

char* const* is basically: ((char*) const)* i.e. A pointer to a char* const pointer.

I guess it helps to visualize the parentheses...
 
It also helps if you read the declaration from right to left; each instance of [tt]const[/tt] applies to the thing directly to its left.

Examples:
Code:
char * const *
|    | |     |
|    | |     +- pointer to
|    | +------- constant
|    +--------- pointer to
+-------------- char

Code:
char * const * const
|    | |     | |
|    | |     | +- constant
|    | |     +--- pointer to
|    | +--------- constant
|    +----------- pointer to
+---------------- char


The exception is that when [tt]const[/tt] is the first thing in a declaration, you apply it to the thing to its right.

Code:
const char * const * const
|     |    | |     | |
|     |    | |     | +- constant
|     |    | |     +--- pointer to
|     |    | +--------- constant
|     |    +----------- pointer to
|     +---------------- [s]char[/s]
+---------------------- constant char


That doesn't have to be an exception, though. A const char is exactly the same thing as a char const. So this is equivalent to the last example:

Code:
char const * const * const
|    |     | |     | |
|    |     | |     | +- constant
|    |     | |     +--- pointer to
|    |     | +--------- constant
|    |     +----------- pointer to
|    +----------------- constant
+---------------------- char

A few people insist on declaring things that way all the time for consistency. I declare most things [tt]const[/tt]-first (since that's what most people do) and remember the exception.
 
I will try to briefly explain the usage of mentioned declaration.
We have a dynamically allocated arrays of char *. Every char * is also allocated.
char * function f() is returning pointer to char* and in function we do sth more or less like below
Code:
char *line;
line=malloc(some_space)
return line

In main we create char** also allocates memmory for it and do sth like that
Code:
char **lines;
while ((line = f())
lines[i]=line
// of course there are a lot of allocs and reallocs to provide proper memory allocations but they are not as important
Than we are trying to sort the array lines using qsort
Qsort (the one from stdlib) takes a pointer to a sorting function.
And below I put the code of that function (which contains that complicated declaration
Code:
int CompareStrings(const void *left, const void *right)
{
   return strcmp(*(char * const *)left, *(char * const *)right);
}
 
I'm wondering if there's any particular reason why they're trying to confuse people? Couldn't they just write:
Code:
return strcmp( (const char*)left, (const char*)right );

I just tried running a program using that CompareStrings() function in VC++ 2005 (compiled as C code) and it crashed!
Code:
#include <string.h>
#include <stdio.h>


int CompareStrings(const void *left, const void *right)
{
   return strcmp( (const char*)left, (const char*)right );

/*  This return crashes...
   return strcmp(*(char * const *)left, *(char * const *)right);
*/
}

int main()
{
	int ret;
	const char str1[] = "Hello";
	const char str2[] = "hello";

	ret = CompareStrings( str1, str2 );

	printf( "ret = %d", ret );

	return 0;
}
When I use (const char*) casting, it works fine.
 
I agree but in the mentioned program it changes a lot. I will put the whole code of the program below.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

char* getline(FILE* infile)
{
char *line = NULL, *tmpline, ch; 
int currsize = 1, currpos = 0; 

while ((ch = fgetc(infile)) != EOF && ch != '\n')
{
 /* if buffer is too small */
 if (currpos >= currsize - 1)
 {
  currsize *= 2; 
  tmpline = realloc(line, currsize); 
  if (tmpline)
   line = tmpline;
  else
  {
   perror("Memory error");
   free(line);
   return NULL;
  }
 }
 
       line[currpos++] = ch;
}

if (currpos)
{
 line[currpos] = '\0';
 return line;
}
else if (ch == '\n') 
 return strdup(""); 
else 
 return NULL;
}

/* !!!! HERE'S THE PROBLEM !!!! */


/* ***************************************** */
int CompareStrings(const void *left, const void *right)
{
   return strcmp(*(char * const *)left, *(char * const *)right);
} /*this version works but it is veeery strange*/
/* ***************************************** */


/* ***************************************** */
int compName(const void *left, const void *right){
return strcmp(*((char **)left), *((char **)right));
} /*this version of compName works as well I've created it myself but I guess it's wrong*/
/* ***************************************** */


/* ***************************************** */
int compName{
return strcmp( (const char*)left, (const char*)right );
}
/* this version doesn't work. Compile with no errors but it doesn't sort array properely*/
/* ***************************************** */


int main(int argc, char *argv[])
{
char **lines=NULL, **tmplines=NULL, *line=NULL;
int numberOfLines=0, i, size;
FILE * infile, *outfile;
int operation;
if (argc!=3){
	printf ("Argument error \n");
	return 1;
	}

infile=fopen(argv[1],"r");
	if (!infile){
	perror("File error");
	exit(1);
	}

outfile=fopen(argv[2],"w");
	if (!infile){
	perror("File error");
	exit(1);
	}


while((line=getline(infile))!=NULL){
tmplines=realloc(lines,(++numberOfLines)*sizeof(char *));
	if(tmplines)
		lines=tmplines;
	else{
		perror("Memory error");
		for(i=0;i<numberOfLines-1;i++)
		free(lines[i]);
		if (lines)
		free (lines);
		return 1;	
	}
lines[numberOfLines-1]=line;
}
qsort(lines,numberOfLines,sizeof(char *),compName);

for (i=0; i<numberOfLines; i++){
operation=fputs(lines[i],outfile);
operation=fputs("\n",outfile);
	if (!operation){/*tu bys zrobil byka!!!!*/
		perror("Error writing data");
		for(i=0;i<numberOfLines-1;i++) /*spisz sobie makroinstrukcje!!!*/
		free(lines[i]);
		if (lines)
		free (lines);
		return 1;
	}
}

for (i=0; i<numberOfLines; i++)
free(lines[i]);
if (lines)
free(lines);
fclose(infile);
fclose(outfile);

return 0;
}

Somebody knows what's wrong. I would be grateful.
 
Code:
int compName{
return strcmp( (const char*)left, (const char*)right );
}
That isn't even a function. I'm extremely surprised that it compiles.


Code:
int CompareStrings(const void *left, const void *right)
{
   return strcmp(*(char * const *)left, *(char * const *)right);
} /*this version works but it is veeery strange*/
When you say it works, but it's very strange, what exactly do you mean? Does it function strange or just look strange?
 
What I wanted to say is that the declaration looks quite strange (const char*)left, (const char*)right The function in fact is very simple, it just returns a value returned by strcmp.
I think that now I also understood it. An array lines /*from the last code I pasted here*/ is just an array of pointers to a const pointers to chars char * const *, so *(char * const *) is just a pointer to such element. Am I right?
As for
Code:
int compName{
return strcmp( (const char*)left, (const char*)right );
}
That isn't even a function. I'm extremely surprised that it compiles.
I obviously forgot to paste function's arguments list (should have been)
Code:
int compName(const void *left, const void *right){
return strcmp( (const char*)left, (const char*)right );
}
I am very sorry.
 
Code:
/* ***************************************** */
int compName(const void *left, const void *right){
return strcmp(*((char **)left), *((char **)right));
} /*this version of compName works as well I've created it myself but I guess it's wrong*/
/* ***************************************** */
Looks fine to me. Works fine, too. Compiles without any warnings.

The [tt]const[/tt] in the "strange" version of the function isn't really doing much, though it's not incorrect.


Also, when you open outfile, you should be error-checking outfile, not infile.
 
Also, when you open outfile, you should be error-checking outfile, not infile.
Obviously you are right. It's my another missprint, again I am sorry for that.
 
No need to apologize; just wanted to make sure your program ends up doing the right thing. :)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top