lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Paige DePol once stated:
> Sean Conner <sean@conman.org> wrote:
> 
> >  -spc (Who realizes that "const char *" is more idiomatic than 
> > 	"char const *" but does the later anyway ... )
> 
> I guess I prefer my qualifier before the type as well.
> 
> Holy chained footnotes, Batman! 

  That was a moderate example---I have been know to go even further!

> > [1]	Why "char const" and not "const char"?  Because "const" actually
> > 	binds to the right (except when it's at the leftmost position).
> > 	[snip]
> 
> I will have to admit that with really complex declarations with multiple uses
> of 'const' I can get confused with what exactly is being declared at times!

  Which is why I started putting the "const" to the right of what it
modifies, to help with decoding.

> > [1]	which is a constant pointer to a function, said function takes two
> > 	FILE *s which are themselves constant [3] and guarenteed not to
> > 	point to the same thing [4].
> > [4]	That's what "restrict" is for.
> 
> That is an interesting qualifier I did not know about... However, you stated
> that it is guaranteed they won't point to the same memory. By guaranteed you
> mean the programmer is the one making that guarantee, and the compiler will
> trust that blindly... and if they do alias the result is undefined [1]. 

  Yes, the compiler is trusting the programmer and results will be undefined
if they are, indeed, the same.

> > [5]	Because C makes it too easy to conflate pointers with arrays.
> 
> Aren't they essentially the same thing though? Array syntax is really just
> sugar for pointer manipulation.

  Erm ... um ... kind of ... somewhat ... but not really ... 

  If you have in file foo.c

	extern char *big_text;

and it's actual declaration in bar.c is

	char big_text[1024];

then you are going to have some issues.  Because foo.c will think of
big_text as:

		 +---+---+---+---+
	big_text | some address  |
		 +---+---+---+---+

where as it's actually defined in bar.c as:

		 +---+---+---+-//-+---+---+---+
	big_text |   |   |   | // |   |   |   |
		 +---+---+---+-//-+---+---+---+

BUT ... as a paramater to a function:

	extern int foo_a(char *big_text);
	extern int foo_b(char big_text[1024]);

are interchangable, as in foo_b(), big_text will actually be a pointer. 
Note that this is for arrays.  The following two functions:

	extern int bar_a(struct foobar x);
	extern int bar_b(struct foobar *x);

are different---the bar_a(), x will be passed by value (that is, the entire
structure will be copied onto the stack).  Now, going back to arrays:

	int  big_array[1024];
	int  single_int;
	int *pa;
	int *pb;
	int *pc;
	int  a;
	int  b;
	int  c; 
	int  d;
	int  e;

	pa = big_array; // okay, big_array referenced here becomes a pointer
	pb = &big_array[0]; // the same as the above line
	pc = single_int; // error---single_int here just returns a value when a pointer is expected
	pc = &single_int; // this is fine

	a = *pa;	// okay
	a = *big_array; // error---big_array is an array, not a pointer
	b = pa[0];	// same as "a = *pa"
	c = *pc;	// also okay
	c = single_int; // still okay
	d = pc[0];	// again okay
	e = pa[2];	// okay, because pa points to big_array and index 2 exists
	e = pc[2];	// undefined bahavior, because pc points to
			// single_int, which is *NOT* an array.

I'm not even going to go into the whole 2[pa] bit here ... but I hope I got
across that pointers and arrays are not exactly the same thing.

> > [7]	We read code more than write it. Spend the extra few seconds writing it.
> 
> Wouldn't this advice apply to "unsigned int" vs "uint" typedefs as well then?

  Yes, and yes, I do use unsigned int from time to time (although you can
get by with just 'unsigned x').  

> I guess one sticking point for me is why is "uint" okay but a shortcut for
> 'const char*' not?

  Well, it depends upon usage.  I'll use 'unsigned int' but not 'uint', but
I will use uint32_t if I'm dealing with data coming from outside (like from
a binary file or a network connection) because it conveys "I want a 32-bit
integer here."  

  Granted, it's a big subjective.

> I can see a typedef that isn't self-explanatory (like my original 'l_str')
> being a problem, but if the typedef name is really just a shorter version of
> the longer name then I don't see why it should be so wrong.

  In my opinion, it's lazy because you are doing so to save typing (again,
subjective).  For example, 'uchar' could be an 'unsigned char', but it could
also be a 'UTF-8 character' (but why not 'utf8char' then?  Because that's
too much to type 8-P

> All that said, I am getting the distinct impression that using a typedef for
> C strings is something that should not be done... okay, more than just an
> impression really. Seriously though, I will take everything that has been
> said under advisement... this has been enlightening and I do appreciate all
> the feedback as I would like to make my code as clean as possible.

  Again, that's subjective.  I consider my code clean, but a friend of mine
just can't comprehend it.  On the flip side, he considers his code to be the
hight of clarity yet I find it to be a maze of twisty uppercase typedefs,
all alike (or to put it another way---it's trying to abstract the
implementation from itself).

  -spc

> [1] https://en.wikipedia.org/wiki/Restrict